From e3c318ded1c1e54fbed019f09534f103806fec94 Mon Sep 17 00:00:00 2001 From: Erik Engervall Date: Fri, 23 Apr 2021 14:39:22 +0200 Subject: [PATCH] Stats: Create individual component for Row children Stats: Improve names for helpers Signed-off-by: Erik Engervall --- .../src/features/Stats/DialogBody.tsx | 38 +-- .../src/features/Stats/Row.tsx | 229 ------------------ .../src/features/Stats/Row/Row.tsx | 96 ++++++++ .../Stats/Row/RowCollapsed/ReleaseTagList.tsx | 71 ++++++ .../Stats/Row/RowCollapsed/ReleaseTime.tsx | 139 +++++++++++ .../Stats/Row/RowCollapsed/RowCollapsed.tsx | 45 ++++ .../src/features/Stats/Warn.tsx | 22 +- .../Stats/helpers/getMappedReleases.tsx | 82 ------- .../Stats/helpers/getReleasesWithTags.tsx | 101 ++++++++ .../src/features/Stats/helpers/getSummary.tsx | 8 +- .../src/features/Stats/helpers/getTags.tsx | 89 ------- .../features/Stats/helpers/mapReleases.tsx | 89 +++++++ 12 files changed, 577 insertions(+), 432 deletions(-) delete mode 100644 plugins/github-release-manager/src/features/Stats/Row.tsx create mode 100644 plugins/github-release-manager/src/features/Stats/Row/Row.tsx create mode 100644 plugins/github-release-manager/src/features/Stats/Row/RowCollapsed/ReleaseTagList.tsx create mode 100644 plugins/github-release-manager/src/features/Stats/Row/RowCollapsed/ReleaseTime.tsx create mode 100644 plugins/github-release-manager/src/features/Stats/Row/RowCollapsed/RowCollapsed.tsx delete mode 100644 plugins/github-release-manager/src/features/Stats/helpers/getMappedReleases.tsx create mode 100644 plugins/github-release-manager/src/features/Stats/helpers/getReleasesWithTags.tsx delete mode 100644 plugins/github-release-manager/src/features/Stats/helpers/getTags.tsx create mode 100644 plugins/github-release-manager/src/features/Stats/helpers/mapReleases.tsx diff --git a/plugins/github-release-manager/src/features/Stats/DialogBody.tsx b/plugins/github-release-manager/src/features/Stats/DialogBody.tsx index d8b406e04b..4248cdc1e8 100644 --- a/plugins/github-release-manager/src/features/Stats/DialogBody.tsx +++ b/plugins/github-release-manager/src/features/Stats/DialogBody.tsx @@ -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() { - {Object.entries(mappedReleases.releases).map( - ([baseVersion, mappedRelease], index) => { + {Object.entries(releasesWithTags.releases).map( + ([baseVersion, releaseWithTags], index) => { return ( ); }, @@ -115,7 +119,7 @@ export function DialogBody() { {shouldWarn && ( - + )} diff --git a/plugins/github-release-manager/src/features/Stats/Row.tsx b/plugins/github-release-manager/src/features/Stats/Row.tsx deleted file mode 100644 index 53ad5751da..0000000000 --- a/plugins/github-release-manager/src/features/Stats/Row.tsx +++ /dev/null @@ -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['releases']['0']; -} - -export function Row({ baseVersion, mappedRelease }: RowProps) { - const [open, setOpen] = useState(false); - const classes = useRowStyles(); - - return ( - - - - setOpen(!open)} - > - {open ? : } - - - - - - {baseVersion} - {mappedRelease.versions.length === 0 ? ' (prerelease)' : ''} - - - - - {mappedRelease.createdAt - ? DateTime.fromISO(mappedRelease.createdAt) - .setLocale('sv-SE') - .toFormat('yyyy-MM-dd') - : '-'} - - - {mappedRelease.candidates.length} - - {Math.max(0, mappedRelease.versions.length - 1)} - - - - - - - - - - - ); -} - -function CollapsedEl({ - mappedRelease, -}: { - mappedRelease: ReturnType['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 ( - - - {mappedRelease.versions.length > 0 && ( - - {mappedRelease.versions.map(version => ( - - {version.tagName} - - ))} - - )} - - {mappedRelease.versions.length > 0 && ( - - {' 🚀 '} - - )} - - - {mappedRelease.candidates.map(candidate => ( - - {candidate.tagName} - - ))} - - - - - {releaseComplete.loading ? ( - - ) : ( - <> - - Release completed{' '} - {releaseComplete.value?.createdAt && - DateTime.fromISO(releaseComplete.value.createdAt) - .setLocale('sv-SE') - .toFormat('yyyy-MM-dd')} - - - - - Release time: {diff.days} days - - - - - RC created{' '} - {releaseCut.value?.createdAt && - DateTime.fromISO(releaseCut.value.createdAt) - .setLocale('sv-SE') - .toFormat('yyyy-MM-dd')} - - - )} - - - ); -} diff --git a/plugins/github-release-manager/src/features/Stats/Row/Row.tsx b/plugins/github-release-manager/src/features/Stats/Row/Row.tsx new file mode 100644 index 0000000000..199aa74fdc --- /dev/null +++ b/plugins/github-release-manager/src/features/Stats/Row/Row.tsx @@ -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 ( + + + + setOpen(!open)} + > + {open ? : } + + + + + + {baseVersion} + {releaseWithTags.versions.length === 0 ? ' (prerelease)' : ''} + + + + + {releaseWithTags.createdAt + ? DateTime.fromISO(releaseWithTags.createdAt) + .setLocale('sv-SE') + .toFormat('yyyy-MM-dd') + : '-'} + + + {releaseWithTags.candidates.length} + + + {Math.max(0, releaseWithTags.versions.length - 1)} + + + + + + + + + + + + ); +} diff --git a/plugins/github-release-manager/src/features/Stats/Row/RowCollapsed/ReleaseTagList.tsx b/plugins/github-release-manager/src/features/Stats/Row/RowCollapsed/ReleaseTagList.tsx new file mode 100644 index 0000000000..3047c310f1 --- /dev/null +++ b/plugins/github-release-manager/src/features/Stats/Row/RowCollapsed/ReleaseTagList.tsx @@ -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 ( + + {releaseWithTags.versions.length > 0 && ( + + {releaseWithTags.versions.map(version => ( + + {version.tagName} + + ))} + + )} + + {releaseWithTags.versions.length > 0 && ( + + {' 🚀 '} + + )} + + + {releaseWithTags.candidates.map(candidate => ( + + {candidate.tagName} + + ))} + + + ); +} diff --git a/plugins/github-release-manager/src/features/Stats/Row/RowCollapsed/ReleaseTime.tsx b/plugins/github-release-manager/src/features/Stats/Row/RowCollapsed/ReleaseTime.tsx new file mode 100644 index 0000000000..b8cc25fd12 --- /dev/null +++ b/plugins/github-release-manager/src/features/Stats/Row/RowCollapsed/ReleaseTime.tsx @@ -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 ( + + + + ); + } + + if (releaseCut.error) { + return ( + + Failed to fetch the first Release Candidate commit ( + {releaseCut.error.message}) + + ); + } + + if (releaseComplete.error) { + return ( + + Failed to fetch the final Release Version Commit ( + {releaseComplete.error.message}) + + ); + } + + 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 ( + + + + Release completed{' '} + {releaseComplete.value?.createdAt && + DateTime.fromISO(releaseComplete.value.createdAt) + .setLocale('sv-SE') + .toFormat('yyyy-MM-dd')} + + + + + + Release time: {diff.days} days + + + + + + Release Candidate created{' '} + {releaseCut.value?.createdAt && + DateTime.fromISO(releaseCut.value.createdAt) + .setLocale('sv-SE') + .toFormat('yyyy-MM-dd')} + + + + ); +} + +function Wrapper({ children }: { children: React.ReactNode }) { + return ( + + {children} + + ); +} diff --git a/plugins/github-release-manager/src/features/Stats/Row/RowCollapsed/RowCollapsed.tsx b/plugins/github-release-manager/src/features/Stats/Row/RowCollapsed/RowCollapsed.tsx new file mode 100644 index 0000000000..a17707a62c --- /dev/null +++ b/plugins/github-release-manager/src/features/Stats/Row/RowCollapsed/RowCollapsed.tsx @@ -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 ( + + + + + + ); +} diff --git a/plugins/github-release-manager/src/features/Stats/Warn.tsx b/plugins/github-release-manager/src/features/Stats/Warn.tsx index b3cb813dfb..a86ac2cf1b 100644 --- a/plugins/github-release-manager/src/features/Stats/Warn.tsx +++ b/plugins/github-release-manager/src/features/Stats/Warn.tsx @@ -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; - mappedReleases: ReturnType; + releasesWithTags: ReturnType['releasesWithTags']; project: Project; } -export const Warn = ({ tags, mappedReleases, project }: WarnProps) => { +export const Warn = ({ releasesWithTags, project }: WarnProps) => { return ( - {tags.unmappable.length > 0 && ( + {releasesWithTags.unmappableTags.length > 0 && (
- Failed to map {tags.unmappable.length} tags to + Failed to map{' '} + {releasesWithTags.unmappableTags.length} tags to releases
)} - {tags.unmatched.length > 0 && ( + {releasesWithTags.unmatchedTags.length > 0 && (
- Failed to match {tags.unmatched.length} tags to{' '} + Failed to match{' '} + {releasesWithTags.unmatchedTags.length} tags to{' '} {project.versioningStrategy}
)} - {mappedReleases.unmatched.length > 0 && ( + {releasesWithTags.unmatched.length > 0 && (
- Failed to match {mappedReleases.unmatched.length}{' '} + Failed to match {releasesWithTags.unmatched.length}{' '} releases to {project.versioningStrategy}
)} diff --git a/plugins/github-release-manager/src/features/Stats/helpers/getMappedReleases.tsx b/plugins/github-release-manager/src/features/Stats/helpers/getMappedReleases.tsx deleted file mode 100644 index af573343e5..0000000000 --- a/plugins/github-release-manager/src/features/Stats/helpers/getMappedReleases.tsx +++ /dev/null @@ -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: {} }, - ); -} diff --git a/plugins/github-release-manager/src/features/Stats/helpers/getReleasesWithTags.tsx b/plugins/github-release-manager/src/features/Stats/helpers/getReleasesWithTags.tsx new file mode 100644 index 0000000000..1c41f78288 --- /dev/null +++ b/plugins/github-release-manager/src/features/Stats/helpers/getReleasesWithTags.tsx @@ -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['mappedReleases']; +}) { + return { + releasesWithTags: allTags.reduce( + ( + acc: ReturnType['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: [], + }, + ), + }; +} diff --git a/plugins/github-release-manager/src/features/Stats/helpers/getSummary.tsx b/plugins/github-release-manager/src/features/Stats/helpers/getSummary.tsx index f90758987b..b898469c8a 100644 --- a/plugins/github-release-manager/src/features/Stats/helpers/getSummary.tsx +++ b/plugins/github-release-manager/src/features/Stats/helpers/getSummary.tsx @@ -14,14 +14,14 @@ * limitations under the License. */ -import { getMappedReleases } from './getMappedReleases'; +import { getReleasesWithTags } from './getReleasesWithTags'; export function getSummary({ - mappedReleases, + releasesWithTags, }: { - mappedReleases: ReturnType; + releasesWithTags: ReturnType['releasesWithTags']; }) { - return Object.entries(mappedReleases.releases).reduce( + return Object.entries(releasesWithTags.releases).reduce( ( acc: { totalReleases: number; diff --git a/plugins/github-release-manager/src/features/Stats/helpers/getTags.tsx b/plugins/github-release-manager/src/features/Stats/helpers/getTags.tsx deleted file mode 100644 index 82d0a6b587..0000000000 --- a/plugins/github-release-manager/src/features/Stats/helpers/getTags.tsx +++ /dev/null @@ -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; -}) { - 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: [] }, - ); -} diff --git a/plugins/github-release-manager/src/features/Stats/helpers/mapReleases.tsx b/plugins/github-release-manager/src/features/Stats/helpers/mapReleases.tsx new file mode 100644 index 0000000000..d1103d5e71 --- /dev/null +++ b/plugins/github-release-manager/src/features/Stats/helpers/mapReleases.tsx @@ -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: {}, + }, + ), + }; +}