Stats: Create individual component for Row children
Stats: Improve names for helpers Signed-off-by: Erik Engervall <erik.engervall@gmail.com>
This commit is contained in:
@@ -29,14 +29,14 @@ import {
|
||||
} from '@material-ui/core';
|
||||
|
||||
import { CenteredCircularProgress } from '../../components/CenteredCircularProgress';
|
||||
import { getMappedReleases } from './helpers/getMappedReleases';
|
||||
import { getMappedReleases } from './helpers/mapReleases';
|
||||
import { getReleasesWithTags } from './helpers/getReleasesWithTags';
|
||||
import { getSummary } from './helpers/getSummary';
|
||||
import { getTags } from './helpers/getTags';
|
||||
import { Row } from './Row';
|
||||
import { Row } from './Row/Row';
|
||||
import { Summary } from './Summary';
|
||||
import { useGetStats } from './hooks/useGetStats';
|
||||
import { useProjectContext } from '../../contexts/ProjectContext';
|
||||
import { Warn } from './Warn';
|
||||
import { Summary } from './Summary';
|
||||
|
||||
const useStyles = makeStyles({
|
||||
table: {
|
||||
@@ -64,20 +64,24 @@ export function DialogBody() {
|
||||
}
|
||||
|
||||
const { allReleases, allTags } = stats.value;
|
||||
const mappedReleases = getMappedReleases({ allReleases, project });
|
||||
const tags = getTags({ allTags, project, mappedReleases });
|
||||
const summary = getSummary({ mappedReleases });
|
||||
const { mappedReleases } = getMappedReleases({ allReleases, project });
|
||||
const { releasesWithTags } = getReleasesWithTags({
|
||||
mappedReleases,
|
||||
allTags,
|
||||
project,
|
||||
});
|
||||
const summary = getSummary({ releasesWithTags });
|
||||
const shouldWarn =
|
||||
tags.unmappable.length > 0 ||
|
||||
tags.unmatched.length > 0 ||
|
||||
mappedReleases.unmatched.length > 0;
|
||||
releasesWithTags.unmappableTags.length > 0 ||
|
||||
releasesWithTags.unmatchedTags.length > 0 ||
|
||||
releasesWithTags.unmatched.length > 0;
|
||||
|
||||
if (shouldWarn) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log("⚠️ Here's a summary of unmapped/unmatched tags/releases", {
|
||||
unmappableTags: tags.unmappable,
|
||||
unmatchableTags: tags.unmatched,
|
||||
unmatchableReleases: mappedReleases.unmatched,
|
||||
unmappableTags: releasesWithTags.unmappableTags,
|
||||
unmatchedTags: releasesWithTags.unmatchedTags,
|
||||
unmatchedReleases: releasesWithTags.unmatched,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -98,13 +102,13 @@ export function DialogBody() {
|
||||
</TableHead>
|
||||
|
||||
<TableBody>
|
||||
{Object.entries(mappedReleases.releases).map(
|
||||
([baseVersion, mappedRelease], index) => {
|
||||
{Object.entries(releasesWithTags.releases).map(
|
||||
([baseVersion, releaseWithTags], index) => {
|
||||
return (
|
||||
<Row
|
||||
key={`row-${index}`}
|
||||
baseVersion={baseVersion}
|
||||
mappedRelease={mappedRelease}
|
||||
releaseWithTags={releaseWithTags}
|
||||
/>
|
||||
);
|
||||
},
|
||||
@@ -115,7 +119,7 @@ export function DialogBody() {
|
||||
|
||||
<Box marginTop={2}>
|
||||
{shouldWarn && (
|
||||
<Warn tags={tags} mappedReleases={mappedReleases} project={project} />
|
||||
<Warn releasesWithTags={releasesWithTags} project={project} />
|
||||
)}
|
||||
</Box>
|
||||
</>
|
||||
|
||||
@@ -1,229 +0,0 @@
|
||||
/*
|
||||
* Copyright 2021 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 { DateTime, DurationObject } from 'luxon';
|
||||
import {
|
||||
Box,
|
||||
Collapse,
|
||||
IconButton,
|
||||
Link,
|
||||
makeStyles,
|
||||
TableCell,
|
||||
TableRow,
|
||||
Typography,
|
||||
} from '@material-ui/core';
|
||||
import KeyboardArrowDownIcon from '@material-ui/icons/KeyboardArrowDown';
|
||||
import KeyboardArrowUpIcon from '@material-ui/icons/KeyboardArrowUp';
|
||||
|
||||
import { getMappedReleases } from './helpers/getMappedReleases';
|
||||
import { useGetCommit } from './hooks/useGetCommit';
|
||||
import { CenteredCircularProgress } from '../../components/CenteredCircularProgress';
|
||||
|
||||
const useRowStyles = makeStyles({
|
||||
root: {
|
||||
'& > *': {
|
||||
borderBottom: 'unset',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
interface RowProps {
|
||||
baseVersion: string;
|
||||
mappedRelease: ReturnType<typeof getMappedReleases>['releases']['0'];
|
||||
}
|
||||
|
||||
export function Row({ baseVersion, mappedRelease }: RowProps) {
|
||||
const [open, setOpen] = useState(false);
|
||||
const classes = useRowStyles();
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<TableRow className={classes.root}>
|
||||
<TableCell>
|
||||
<IconButton
|
||||
aria-label="expand row"
|
||||
size="small"
|
||||
onClick={() => setOpen(!open)}
|
||||
>
|
||||
{open ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />}
|
||||
</IconButton>
|
||||
</TableCell>
|
||||
|
||||
<TableCell component="th" scope="row">
|
||||
<Link href={mappedRelease.htmlUrl} target="_blank">
|
||||
{baseVersion}
|
||||
{mappedRelease.versions.length === 0 ? ' (prerelease)' : ''}
|
||||
</Link>
|
||||
</TableCell>
|
||||
|
||||
<TableCell>
|
||||
{mappedRelease.createdAt
|
||||
? DateTime.fromISO(mappedRelease.createdAt)
|
||||
.setLocale('sv-SE')
|
||||
.toFormat('yyyy-MM-dd')
|
||||
: '-'}
|
||||
</TableCell>
|
||||
|
||||
<TableCell>{mappedRelease.candidates.length}</TableCell>
|
||||
|
||||
<TableCell>{Math.max(0, mappedRelease.versions.length - 1)}</TableCell>
|
||||
</TableRow>
|
||||
|
||||
<TableRow>
|
||||
<TableCell style={{ paddingBottom: 0, paddingTop: 0 }} colSpan={6}>
|
||||
<Collapse in={open} timeout="auto" unmountOnExit>
|
||||
<CollapsedEl mappedRelease={mappedRelease} />
|
||||
</Collapse>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
function CollapsedEl({
|
||||
mappedRelease,
|
||||
}: {
|
||||
mappedRelease: ReturnType<typeof getMappedReleases>['releases']['0'];
|
||||
}) {
|
||||
const reversedCandidates = [...mappedRelease.candidates].reverse();
|
||||
|
||||
const { commit: releaseCut } = useGetCommit({
|
||||
ref: reversedCandidates[0]?.sha,
|
||||
});
|
||||
const { commit: releaseComplete } = useGetCommit({
|
||||
ref: mappedRelease.versions[0]?.sha,
|
||||
});
|
||||
|
||||
console.log('*** releaseCut > ', releaseCut.value); // eslint-disable-line no-console
|
||||
console.log('*** releaseComplete > ', releaseComplete.value); // eslint-disable-line no-console
|
||||
|
||||
let diff = { days: -1 } as DurationObject;
|
||||
if (releaseCut.value?.createdAt && releaseComplete.value?.createdAt) {
|
||||
diff = DateTime.fromISO(releaseComplete.value.createdAt)
|
||||
.diff(DateTime.fromISO(releaseCut.value.createdAt), ['days', 'hours'])
|
||||
.toObject();
|
||||
}
|
||||
|
||||
return (
|
||||
<Box
|
||||
margin={1}
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'stretch',
|
||||
paddingLeft: '20%',
|
||||
paddingRight: '20%',
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
style={{
|
||||
flex: 1,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
{mappedRelease.versions.length > 0 && (
|
||||
<Box margin={1} style={{ position: 'relative' }}>
|
||||
{mappedRelease.versions.map(version => (
|
||||
<React.Fragment key={version.tagName}>
|
||||
<Typography variant="body1">{version.tagName}</Typography>
|
||||
</React.Fragment>
|
||||
))}
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{mappedRelease.versions.length > 0 && (
|
||||
<Box
|
||||
margin={1}
|
||||
style={{
|
||||
position: 'relative',
|
||||
transform: 'rotate(-45deg)',
|
||||
fontSize: 30,
|
||||
}}
|
||||
>
|
||||
{' 🚀 '}
|
||||
</Box>
|
||||
)}
|
||||
|
||||
<Box margin={1} style={{ position: 'relative' }}>
|
||||
{mappedRelease.candidates.map(candidate => (
|
||||
<React.Fragment key={candidate.tagName}>
|
||||
<Typography variant="body1">{candidate.tagName}</Typography>
|
||||
</React.Fragment>
|
||||
))}
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<Box
|
||||
style={{
|
||||
flex: 1,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
{releaseComplete.loading ? (
|
||||
<CenteredCircularProgress />
|
||||
) : (
|
||||
<>
|
||||
<Box
|
||||
style={{
|
||||
flex: 1,
|
||||
display: 'flex',
|
||||
alignItems: 'flex-end',
|
||||
}}
|
||||
>
|
||||
Release completed{' '}
|
||||
{releaseComplete.value?.createdAt &&
|
||||
DateTime.fromISO(releaseComplete.value.createdAt)
|
||||
.setLocale('sv-SE')
|
||||
.toFormat('yyyy-MM-dd')}
|
||||
</Box>
|
||||
|
||||
<Box
|
||||
style={{
|
||||
flex: 1,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<Typography variant="h4">
|
||||
Release time: {diff.days} days
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
<Box
|
||||
style={{
|
||||
flex: 1,
|
||||
display: 'flex',
|
||||
alignItems: 'flex-start',
|
||||
}}
|
||||
>
|
||||
RC created{' '}
|
||||
{releaseCut.value?.createdAt &&
|
||||
DateTime.fromISO(releaseCut.value.createdAt)
|
||||
.setLocale('sv-SE')
|
||||
.toFormat('yyyy-MM-dd')}
|
||||
</Box>
|
||||
</>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright 2021 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 { DateTime } from 'luxon';
|
||||
import {
|
||||
Collapse,
|
||||
IconButton,
|
||||
Link,
|
||||
makeStyles,
|
||||
TableCell,
|
||||
TableRow,
|
||||
} from '@material-ui/core';
|
||||
import KeyboardArrowDownIcon from '@material-ui/icons/KeyboardArrowDown';
|
||||
import KeyboardArrowUpIcon from '@material-ui/icons/KeyboardArrowUp';
|
||||
|
||||
import { getReleasesWithTags } from '../helpers/getReleasesWithTags';
|
||||
import { RowCollapsed } from './RowCollapsed/RowCollapsed';
|
||||
|
||||
const useRowStyles = makeStyles({
|
||||
root: {
|
||||
'& > *': {
|
||||
borderBottom: 'unset',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
interface RowProps {
|
||||
baseVersion: string;
|
||||
releaseWithTags: ReturnType<
|
||||
typeof getReleasesWithTags
|
||||
>['releasesWithTags']['releases']['0'];
|
||||
}
|
||||
|
||||
export function Row({ baseVersion, releaseWithTags }: RowProps) {
|
||||
const [open, setOpen] = useState(false);
|
||||
const classes = useRowStyles();
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<TableRow className={classes.root}>
|
||||
<TableCell>
|
||||
<IconButton
|
||||
aria-label="expand row"
|
||||
size="small"
|
||||
onClick={() => setOpen(!open)}
|
||||
>
|
||||
{open ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />}
|
||||
</IconButton>
|
||||
</TableCell>
|
||||
|
||||
<TableCell component="th" scope="row">
|
||||
<Link href={releaseWithTags.htmlUrl} target="_blank">
|
||||
{baseVersion}
|
||||
{releaseWithTags.versions.length === 0 ? ' (prerelease)' : ''}
|
||||
</Link>
|
||||
</TableCell>
|
||||
|
||||
<TableCell>
|
||||
{releaseWithTags.createdAt
|
||||
? DateTime.fromISO(releaseWithTags.createdAt)
|
||||
.setLocale('sv-SE')
|
||||
.toFormat('yyyy-MM-dd')
|
||||
: '-'}
|
||||
</TableCell>
|
||||
|
||||
<TableCell>{releaseWithTags.candidates.length}</TableCell>
|
||||
|
||||
<TableCell>
|
||||
{Math.max(0, releaseWithTags.versions.length - 1)}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
|
||||
<TableRow>
|
||||
<TableCell style={{ paddingBottom: 0, paddingTop: 0 }} colSpan={6}>
|
||||
<Collapse in={open} timeout="auto" unmountOnExit>
|
||||
<RowCollapsed releaseWithTags={releaseWithTags} />
|
||||
</Collapse>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2021 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 { Box, Typography } from '@material-ui/core';
|
||||
|
||||
import { getReleasesWithTags } from '../../helpers/getReleasesWithTags';
|
||||
|
||||
export function ReleaseTagList({
|
||||
releaseWithTags,
|
||||
}: {
|
||||
releaseWithTags: ReturnType<
|
||||
typeof getReleasesWithTags
|
||||
>['releasesWithTags']['releases']['0'];
|
||||
}) {
|
||||
return (
|
||||
<Box
|
||||
style={{
|
||||
flex: 1,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
{releaseWithTags.versions.length > 0 && (
|
||||
<Box style={{ position: 'relative' }}>
|
||||
{releaseWithTags.versions.map(version => (
|
||||
<Typography variant="body1" key={version.tagName}>
|
||||
{version.tagName}
|
||||
</Typography>
|
||||
))}
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{releaseWithTags.versions.length > 0 && (
|
||||
<Box
|
||||
margin={1}
|
||||
style={{
|
||||
position: 'relative',
|
||||
transform: 'rotate(-45deg)',
|
||||
fontSize: 30,
|
||||
}}
|
||||
>
|
||||
{' 🚀 '}
|
||||
</Box>
|
||||
)}
|
||||
|
||||
<Box style={{ position: 'relative' }}>
|
||||
{releaseWithTags.candidates.map(candidate => (
|
||||
<Typography variant="body1" key={candidate.tagName}>
|
||||
{candidate.tagName}
|
||||
</Typography>
|
||||
))}
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright 2021 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 { Box, Typography } from '@material-ui/core';
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
import { CenteredCircularProgress } from '../../../../components/CenteredCircularProgress';
|
||||
import { getReleasesWithTags } from '../../helpers/getReleasesWithTags';
|
||||
import { useGetCommit } from '../../hooks/useGetCommit';
|
||||
import { Alert } from '@material-ui/lab';
|
||||
|
||||
interface ReleaseTimeProps {
|
||||
releaseWithTags: ReturnType<
|
||||
typeof getReleasesWithTags
|
||||
>['releasesWithTags']['releases']['0'];
|
||||
}
|
||||
|
||||
export function ReleaseTime({ releaseWithTags }: ReleaseTimeProps) {
|
||||
const reversedCandidates = [...releaseWithTags.candidates].reverse();
|
||||
|
||||
const firstCandidateSha = reversedCandidates[0]?.sha;
|
||||
const { commit: releaseCut } = useGetCommit({ ref: firstCandidateSha });
|
||||
|
||||
const mostRecentVersionSha = releaseWithTags.versions[0]?.sha;
|
||||
const { commit: releaseComplete } = useGetCommit({
|
||||
ref: mostRecentVersionSha,
|
||||
});
|
||||
|
||||
if (releaseCut.loading || releaseComplete.loading) {
|
||||
return (
|
||||
<Wrapper>
|
||||
<CenteredCircularProgress />
|
||||
</Wrapper>
|
||||
);
|
||||
}
|
||||
|
||||
if (releaseCut.error) {
|
||||
return (
|
||||
<Alert severity="error">
|
||||
Failed to fetch the first Release Candidate commit (
|
||||
{releaseCut.error.message})
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
|
||||
if (releaseComplete.error) {
|
||||
return (
|
||||
<Alert severity="error">
|
||||
Failed to fetch the final Release Version Commit (
|
||||
{releaseComplete.error.message})
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
|
||||
const diff =
|
||||
releaseCut.value?.createdAt && releaseComplete.value?.createdAt
|
||||
? DateTime.fromISO(releaseComplete.value.createdAt)
|
||||
.diff(DateTime.fromISO(releaseCut.value.createdAt), ['days', 'hours'])
|
||||
.toObject()
|
||||
: { days: -1 };
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<Box
|
||||
style={{
|
||||
flex: 1,
|
||||
display: 'flex',
|
||||
alignItems: 'flex-start',
|
||||
}}
|
||||
>
|
||||
<Typography variant="body1">
|
||||
Release completed{' '}
|
||||
{releaseComplete.value?.createdAt &&
|
||||
DateTime.fromISO(releaseComplete.value.createdAt)
|
||||
.setLocale('sv-SE')
|
||||
.toFormat('yyyy-MM-dd')}
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
<Box
|
||||
style={{
|
||||
flex: 1,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<Typography variant="h5" color="secondary">
|
||||
Release time: {diff.days} days
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
<Box
|
||||
style={{
|
||||
flex: 1,
|
||||
display: 'flex',
|
||||
alignItems: 'flex-end',
|
||||
}}
|
||||
>
|
||||
<Typography variant="body1">
|
||||
Release Candidate created{' '}
|
||||
{releaseCut.value?.createdAt &&
|
||||
DateTime.fromISO(releaseCut.value.createdAt)
|
||||
.setLocale('sv-SE')
|
||||
.toFormat('yyyy-MM-dd')}
|
||||
</Typography>
|
||||
</Box>
|
||||
</Wrapper>
|
||||
);
|
||||
}
|
||||
|
||||
function Wrapper({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<Box
|
||||
style={{
|
||||
flex: 1,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2021 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 { Box } from '@material-ui/core';
|
||||
|
||||
import { getReleasesWithTags } from '../../helpers/getReleasesWithTags';
|
||||
import { ReleaseTime } from './ReleaseTime';
|
||||
import { ReleaseTagList } from './ReleaseTagList';
|
||||
|
||||
interface RowCollapsedProps {
|
||||
releaseWithTags: ReturnType<
|
||||
typeof getReleasesWithTags
|
||||
>['releasesWithTags']['releases']['0'];
|
||||
}
|
||||
|
||||
export function RowCollapsed({ releaseWithTags }: RowCollapsedProps) {
|
||||
return (
|
||||
<Box
|
||||
margin={1}
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'stretch',
|
||||
paddingLeft: '10%',
|
||||
paddingRight: '10%',
|
||||
}}
|
||||
>
|
||||
<ReleaseTagList releaseWithTags={releaseWithTags} />
|
||||
|
||||
<ReleaseTime releaseWithTags={releaseWithTags} />
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
@@ -17,36 +17,36 @@
|
||||
import React from 'react';
|
||||
import { Alert } from '@material-ui/lab';
|
||||
|
||||
import { getMappedReleases } from './helpers/getMappedReleases';
|
||||
import { getTags } from './helpers/getTags';
|
||||
import { getReleasesWithTags } from './helpers/getReleasesWithTags';
|
||||
import { Project } from '../../contexts/ProjectContext';
|
||||
|
||||
interface WarnProps {
|
||||
tags: ReturnType<typeof getTags>;
|
||||
mappedReleases: ReturnType<typeof getMappedReleases>;
|
||||
releasesWithTags: ReturnType<typeof getReleasesWithTags>['releasesWithTags'];
|
||||
project: Project;
|
||||
}
|
||||
|
||||
export const Warn = ({ tags, mappedReleases, project }: WarnProps) => {
|
||||
export const Warn = ({ releasesWithTags, project }: WarnProps) => {
|
||||
return (
|
||||
<Alert severity="warning" style={{ marginBottom: 10 }}>
|
||||
{tags.unmappable.length > 0 && (
|
||||
{releasesWithTags.unmappableTags.length > 0 && (
|
||||
<div>
|
||||
Failed to map <strong>{tags.unmappable.length}</strong> tags to
|
||||
Failed to map{' '}
|
||||
<strong>{releasesWithTags.unmappableTags.length}</strong> tags to
|
||||
releases
|
||||
</div>
|
||||
)}
|
||||
|
||||
{tags.unmatched.length > 0 && (
|
||||
{releasesWithTags.unmatchedTags.length > 0 && (
|
||||
<div>
|
||||
Failed to match <strong>{tags.unmatched.length}</strong> tags to{' '}
|
||||
Failed to match{' '}
|
||||
<strong>{releasesWithTags.unmatchedTags.length}</strong> tags to{' '}
|
||||
{project.versioningStrategy}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{mappedReleases.unmatched.length > 0 && (
|
||||
{releasesWithTags.unmatched.length > 0 && (
|
||||
<div>
|
||||
Failed to match <strong>{mappedReleases.unmatched.length}</strong>{' '}
|
||||
Failed to match <strong>{releasesWithTags.unmatched.length}</strong>{' '}
|
||||
releases to {project.versioningStrategy}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
* Copyright 2021 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 { calverRegexp } from '../../../helpers/tagParts/getCalverTagParts';
|
||||
import { GetAllReleasesResult } from '../../../api/PluginApiClient';
|
||||
import { Project } from '../../../contexts/ProjectContext';
|
||||
import { semverRegexp } from '../../../helpers/tagParts/getSemverTagParts';
|
||||
|
||||
export function getMappedReleases({
|
||||
allReleases,
|
||||
project,
|
||||
}: {
|
||||
allReleases: GetAllReleasesResult;
|
||||
project: Project;
|
||||
}) {
|
||||
return allReleases.reduce(
|
||||
(
|
||||
acc: {
|
||||
unmatched: string[];
|
||||
releases: {
|
||||
[baseVersion: string]: {
|
||||
createdAt: string | null;
|
||||
candidates: {
|
||||
tagName: string;
|
||||
sha: string;
|
||||
}[];
|
||||
versions: {
|
||||
tagName: string;
|
||||
sha: string;
|
||||
}[];
|
||||
htmlUrl: string;
|
||||
};
|
||||
};
|
||||
},
|
||||
release,
|
||||
) => {
|
||||
const match =
|
||||
project.versioningStrategy === 'semver'
|
||||
? release.tagName.match(semverRegexp)
|
||||
: release.tagName.match(calverRegexp);
|
||||
|
||||
if (!match) {
|
||||
acc.unmatched.push(release.tagName);
|
||||
return acc;
|
||||
}
|
||||
|
||||
const prefix = match[1];
|
||||
const baseVersion =
|
||||
project.versioningStrategy === 'semver'
|
||||
? `${match[2]}.${match[3]}`
|
||||
: match[2];
|
||||
|
||||
if (!acc.releases[baseVersion]) {
|
||||
acc.releases[baseVersion] = {
|
||||
createdAt: release.createdAt,
|
||||
candidates:
|
||||
prefix === 'rc' ? [{ tagName: release.tagName, sha: '' }] : [],
|
||||
versions:
|
||||
prefix === 'version' ? [{ tagName: release.tagName, sha: '' }] : [],
|
||||
htmlUrl: release.htmlUrl,
|
||||
};
|
||||
return acc;
|
||||
}
|
||||
|
||||
return acc;
|
||||
},
|
||||
{ unmatched: [], releases: {} },
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright 2021 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 { calverRegexp } from '../../../helpers/tagParts/getCalverTagParts';
|
||||
import { GetAllTagsResult } from '../../../api/PluginApiClient';
|
||||
import { getMappedReleases } from './mapReleases';
|
||||
import { Project } from '../../../contexts/ProjectContext';
|
||||
import { semverRegexp } from '../../../helpers/tagParts/getSemverTagParts';
|
||||
|
||||
export function getReleasesWithTags({
|
||||
allTags,
|
||||
project,
|
||||
mappedReleases,
|
||||
}: {
|
||||
allTags: GetAllTagsResult;
|
||||
project: Project;
|
||||
mappedReleases: ReturnType<typeof getMappedReleases>['mappedReleases'];
|
||||
}) {
|
||||
return {
|
||||
releasesWithTags: allTags.reduce(
|
||||
(
|
||||
acc: ReturnType<typeof getMappedReleases>['mappedReleases'] & {
|
||||
unmatchedTags: string[];
|
||||
unmappableTags: string[];
|
||||
},
|
||||
tag,
|
||||
) => {
|
||||
const match =
|
||||
project.versioningStrategy === 'semver'
|
||||
? tag.tagName.match(semverRegexp)
|
||||
: tag.tagName.match(calverRegexp);
|
||||
|
||||
if (!match) {
|
||||
acc.unmatchedTags.push(tag.tagName);
|
||||
return acc;
|
||||
}
|
||||
|
||||
const prefix = match[1];
|
||||
const baseVersion =
|
||||
project.versioningStrategy === 'semver'
|
||||
? `${match[2]}.${match[3]}`
|
||||
: match[2];
|
||||
|
||||
if (!acc.releases[baseVersion]) {
|
||||
acc.unmappableTags.push(tag.tagName);
|
||||
return acc;
|
||||
}
|
||||
|
||||
if (prefix === 'rc') {
|
||||
const existingEntry = acc.releases[baseVersion].candidates.find(
|
||||
({ tagName }) => tagName === tag.tagName,
|
||||
);
|
||||
|
||||
if (existingEntry) {
|
||||
existingEntry.sha = tag.sha;
|
||||
} else {
|
||||
acc.releases[baseVersion].candidates.push({
|
||||
tagName: tag.tagName,
|
||||
sha: tag.sha,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (prefix === 'version') {
|
||||
const existingEntry = acc.releases[baseVersion].versions.find(
|
||||
({ tagName }) => tagName === tag.tagName,
|
||||
);
|
||||
|
||||
if (existingEntry) {
|
||||
existingEntry.sha = tag.sha;
|
||||
} else {
|
||||
acc.releases[baseVersion].versions.push({
|
||||
tagName: tag.tagName,
|
||||
sha: tag.sha,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return acc;
|
||||
},
|
||||
{
|
||||
...mappedReleases,
|
||||
unmatchedTags: [],
|
||||
unmappableTags: [],
|
||||
},
|
||||
),
|
||||
};
|
||||
}
|
||||
@@ -14,14 +14,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { getMappedReleases } from './getMappedReleases';
|
||||
import { getReleasesWithTags } from './getReleasesWithTags';
|
||||
|
||||
export function getSummary({
|
||||
mappedReleases,
|
||||
releasesWithTags,
|
||||
}: {
|
||||
mappedReleases: ReturnType<typeof getMappedReleases>;
|
||||
releasesWithTags: ReturnType<typeof getReleasesWithTags>['releasesWithTags'];
|
||||
}) {
|
||||
return Object.entries(mappedReleases.releases).reduce(
|
||||
return Object.entries(releasesWithTags.releases).reduce(
|
||||
(
|
||||
acc: {
|
||||
totalReleases: number;
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
* Copyright 2021 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 { calverRegexp } from '../../../helpers/tagParts/getCalverTagParts';
|
||||
import { GetAllTagsResult } from '../../../api/PluginApiClient';
|
||||
import { getMappedReleases } from './getMappedReleases';
|
||||
import { Project } from '../../../contexts/ProjectContext';
|
||||
import { semverRegexp } from '../../../helpers/tagParts/getSemverTagParts';
|
||||
|
||||
export function getTags({
|
||||
allTags,
|
||||
project,
|
||||
mappedReleases,
|
||||
}: {
|
||||
allTags: GetAllTagsResult;
|
||||
project: Project;
|
||||
mappedReleases: ReturnType<typeof getMappedReleases>;
|
||||
}) {
|
||||
return allTags.reduce(
|
||||
(acc: { unmatched: string[]; unmappable: string[] }, tag) => {
|
||||
const match =
|
||||
project.versioningStrategy === 'semver'
|
||||
? tag.tagName.match(semverRegexp)
|
||||
: tag.tagName.match(calverRegexp);
|
||||
|
||||
if (!match) {
|
||||
acc.unmatched.push(tag.tagName);
|
||||
return acc;
|
||||
}
|
||||
|
||||
const prefix = match[1];
|
||||
const baseVersion =
|
||||
project.versioningStrategy === 'semver'
|
||||
? `${match[2]}.${match[3]}`
|
||||
: match[2];
|
||||
|
||||
if (!mappedReleases.releases[baseVersion]) {
|
||||
acc.unmappable.push(tag.tagName);
|
||||
return acc;
|
||||
}
|
||||
|
||||
if (prefix === 'rc') {
|
||||
const existingEntry = mappedReleases.releases[
|
||||
baseVersion
|
||||
].candidates.find(({ tagName }) => tagName === tag.tagName);
|
||||
|
||||
if (existingEntry) {
|
||||
existingEntry.sha = tag.sha;
|
||||
} else {
|
||||
mappedReleases.releases[baseVersion].candidates.push({
|
||||
tagName: tag.tagName,
|
||||
sha: tag.sha,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (prefix === 'version') {
|
||||
const existingEntry = mappedReleases.releases[
|
||||
baseVersion
|
||||
].versions.find(({ tagName }) => tagName === tag.tagName);
|
||||
|
||||
if (existingEntry) {
|
||||
existingEntry.sha = tag.sha;
|
||||
} else {
|
||||
mappedReleases.releases[baseVersion].versions.push({
|
||||
tagName: tag.tagName,
|
||||
sha: tag.sha,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return acc;
|
||||
},
|
||||
{ unmatched: [], unmappable: [] },
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright 2021 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 { calverRegexp } from '../../../helpers/tagParts/getCalverTagParts';
|
||||
import { GetAllReleasesResult } from '../../../api/PluginApiClient';
|
||||
import { Project } from '../../../contexts/ProjectContext';
|
||||
import { semverRegexp } from '../../../helpers/tagParts/getSemverTagParts';
|
||||
|
||||
export function getMappedReleases({
|
||||
allReleases,
|
||||
project,
|
||||
}: {
|
||||
allReleases: GetAllReleasesResult;
|
||||
project: Project;
|
||||
}) {
|
||||
return {
|
||||
mappedReleases: allReleases.reduce(
|
||||
(
|
||||
acc: {
|
||||
unmatched: string[];
|
||||
releases: {
|
||||
[baseVersion: string]: {
|
||||
createdAt: string | null;
|
||||
candidates: {
|
||||
tagName: string;
|
||||
sha: string;
|
||||
}[];
|
||||
versions: {
|
||||
tagName: string;
|
||||
sha: string;
|
||||
}[];
|
||||
htmlUrl: string;
|
||||
};
|
||||
};
|
||||
},
|
||||
release,
|
||||
) => {
|
||||
const match =
|
||||
project.versioningStrategy === 'semver'
|
||||
? release.tagName.match(semverRegexp)
|
||||
: release.tagName.match(calverRegexp);
|
||||
|
||||
if (!match) {
|
||||
acc.unmatched.push(release.tagName);
|
||||
return acc;
|
||||
}
|
||||
|
||||
const prefix = match[1];
|
||||
const baseVersion =
|
||||
project.versioningStrategy === 'semver'
|
||||
? `${match[2]}.${match[3]}`
|
||||
: match[2];
|
||||
|
||||
if (!acc.releases[baseVersion]) {
|
||||
acc.releases[baseVersion] = {
|
||||
createdAt: release.createdAt,
|
||||
candidates:
|
||||
prefix === 'rc' ? [{ tagName: release.tagName, sha: '' }] : [],
|
||||
versions:
|
||||
prefix === 'version'
|
||||
? [{ tagName: release.tagName, sha: '' }]
|
||||
: [],
|
||||
htmlUrl: release.htmlUrl,
|
||||
};
|
||||
return acc;
|
||||
}
|
||||
|
||||
return acc;
|
||||
},
|
||||
{
|
||||
unmatched: [],
|
||||
releases: {},
|
||||
},
|
||||
),
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user