Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 27 additions & 10 deletions src/common/github-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,33 @@ function filterPrsForVersion(
version: string,
ignoredVersionLabels: readonly string[] = []
): PrItem[] {
return prs.filter((pr) => {
const prVersions = pr.labels
.filter((label) => label.name?.match(SEMVER_REGEX))
.filter((label) => label.name && !ignoredVersionLabels.includes(label.name))
.map((label) => semver.clean(label.name ?? '') ?? '');
// Check if there is any version label below the one we are looking for
// which would mean this PR has already been released (and blogged about)
// in an earlier dev documentation blog post.
return !prVersions.some((verLabel) => semver.lt(verLabel, version));
});
// No longer filtering out PRs with lower version labels
// Just return all PRs, the warning logic is handled separately
return prs;
}

/**
* Checks if a PR has multiple patch version labels for the same major.minor version.
* This indicates the PR may have been documented in multiple patch releases.
*/
export function hasDuplicatePatchLabels(pr: PrItem, targetVersion: string): boolean {
const targetSemVer = semver.parse(targetVersion);
if (!targetSemVer) {
return false;
}

const prVersions = pr.labels
.filter((label) => label.name?.match(SEMVER_REGEX))
.map((label) => semver.parse(label.name ?? ''))
.filter((ver): ver is semver.SemVer => ver !== null);

// Find all version labels that match the same major.minor as target
const sameMajorMinor = prVersions.filter(
(ver) => ver.major === targetSemVer.major && ver.minor === targetSemVer.minor
);

// If there are 2 or more patch versions for the same major.minor, return true
return sameMajorMinor.length >= 2;
}

export class GitHubService {
Expand Down
19 changes: 17 additions & 2 deletions src/common/pr.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
import { EuiLink, EuiIconTip } from '@elastic/eui';
import { FC, memo } from 'react';
import { PrItem } from './github-service';
import { PrItem, hasDuplicatePatchLabels } from './github-service';
import { extractReleaseNotes, NormalizeOptions, ReleaseNoteDetails } from './pr-utils';

interface PrProps {
pr: PrItem;
showAuthor?: boolean;
showTransformedTitle?: boolean;
normalizeOptions?: NormalizeOptions;
version?: string;
}

export const Pr: FC<PrProps> = memo(
({ pr, showAuthor, showTransformedTitle, normalizeOptions }) => {
({ pr, showAuthor, showTransformedTitle, normalizeOptions, version }) => {
const title: ReleaseNoteDetails = showTransformedTitle
? extractReleaseNotes(pr, normalizeOptions)
: { type: 'title', title: pr.title };
const hasDuplicates = version ? hasDuplicatePatchLabels(pr, version) : false;
return (
<>
{title.title} (
Expand All @@ -27,6 +29,19 @@ export const Pr: FC<PrProps> = memo(
</>
)}
){' '}
{hasDuplicates && (
<EuiIconTip
color="warning"
type="alert"
size="m"
content={
<>
This PR has multiple patch version labels for the same major.minor version. It may
have already been documented in a previous patch release.
</>
}
/>
)}
{title.type === 'releaseNoteTitle' && (
<EuiIconTip
color="secondary"
Expand Down
10 changes: 8 additions & 2 deletions src/pages/release-notes/components/grouped-pr-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ interface Props {
groupedPrs: { [group: string]: PrItem[] };
groups: Config['areas'];
keyPrefix: string;
version: string;
}

export const GroupedPrList: FC<Props> = memo(({ groupedPrs, groups, keyPrefix }) => {
export const GroupedPrList: FC<Props> = memo(({ groupedPrs, groups, keyPrefix, version }) => {
const sortedGroups = useMemo(
() => [...groups].sort((a, b) => a.title.localeCompare(b.title)),
[groups]
Expand Down Expand Up @@ -37,7 +38,12 @@ export const GroupedPrList: FC<Props> = memo(({ groupedPrs, groups, keyPrefix })
<ul>
{prs.map((pr) => (
<li key={pr.id}>
<Pr pr={pr} showTransformedTitle={true} normalizeOptions={group.options} />
<Pr
pr={pr}
showTransformedTitle={true}
normalizeOptions={group.options}
version={version}
/>
</li>
))}
</ul>
Expand Down
5 changes: 3 additions & 2 deletions src/pages/release-notes/components/uncategorized-pr.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { setConfig, useActiveConfig } from '../../../config';

interface UncategorizedPrProps {
pr: PrItem;
version: string;
}

const LabelBadge: FC<{ label: Label }> = memo(({ label }) => {
Expand Down Expand Up @@ -83,7 +84,7 @@ const LabelBadge: FC<{ label: Label }> = memo(({ label }) => {
);
});

export const UncategorizedPr: FC<UncategorizedPrProps> = memo(({ pr }) => {
export const UncategorizedPr: FC<UncategorizedPrProps> = memo(({ pr, version }) => {
// We only want to show non version non release_note labels in the UI
const filteredLables = useMemo(
() =>
Expand All @@ -95,7 +96,7 @@ export const UncategorizedPr: FC<UncategorizedPrProps> = memo(({ pr }) => {
return (
<EuiSplitPanel.Outer>
<EuiSplitPanel.Inner paddingSize="s">
<Pr pr={pr} showAuthor={true} />
<Pr pr={pr} showAuthor={true} version={version} />
</EuiSplitPanel.Inner>
<EuiSplitPanel.Inner paddingSize="s" color="subdued">
{filteredLables.length > 0 && (
Expand Down
26 changes: 19 additions & 7 deletions src/pages/release-notes/prepare-release-notes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import { GroupedPrList, UncategorizedPr } from './components';

interface Props {
prs: PrItem[];
version: string;
}

export const PrepareReleaseNotes: FC<Props> = ({ prs }) => {
export const PrepareReleaseNotes: FC<Props> = ({ prs, version }) => {
const config = useActiveConfig();
const groupedPrs = useMemo(() => groupPrs(prs), [prs]);

Expand Down Expand Up @@ -49,7 +50,7 @@ export const PrepareReleaseNotes: FC<Props> = ({ prs }) => {
<ul>
{groupedPrs.missingLabel.map((pr) => (
<li key={pr.id}>
<Pr pr={pr} showAuthor={true} />
<Pr pr={pr} showAuthor={true} version={version} />
</li>
))}
</ul>
Expand All @@ -73,7 +74,7 @@ export const PrepareReleaseNotes: FC<Props> = ({ prs }) => {
<EuiSpacer size="m" />
{unknownPrs.map((pr) => (
<React.Fragment key={pr.id}>
<UncategorizedPr pr={pr} />
<UncategorizedPr pr={pr} version={version} />
<EuiSpacer size="s" />
</React.Fragment>
))}
Expand All @@ -87,7 +88,7 @@ export const PrepareReleaseNotes: FC<Props> = ({ prs }) => {
<ul>
{groupedPrs.breaking.map((pr) => (
<li key={`breaking-${pr.id}`}>
<Pr pr={pr} showTransformedTitle={true} />
<Pr pr={pr} showTransformedTitle={true} version={version} />
</li>
))}
</ul>
Expand All @@ -101,7 +102,7 @@ export const PrepareReleaseNotes: FC<Props> = ({ prs }) => {
<ul>
{groupedPrs.deprecation.map((pr) => (
<li key={`deprecation-${pr.id}`}>
<Pr pr={pr} showTransformedTitle={true} />
<Pr pr={pr} showTransformedTitle={true} version={version} />
</li>
))}
</ul>
Expand All @@ -112,7 +113,12 @@ export const PrepareReleaseNotes: FC<Props> = ({ prs }) => {
<h2>
Features (<EuiCode>release_note:feature</EuiCode>)
</h2>
<GroupedPrList groupedPrs={featurePrs} groups={config.areas} keyPrefix="features" />
<GroupedPrList
groupedPrs={featurePrs}
groups={config.areas}
keyPrefix="features"
version={version}
/>
</>
)}
{Object.keys(enhancementPrs).length > 0 && (
Expand All @@ -124,6 +130,7 @@ export const PrepareReleaseNotes: FC<Props> = ({ prs }) => {
groupedPrs={enhancementPrs}
groups={config.areas}
keyPrefix="enhancements"
version={version}
/>
</>
)}
Expand All @@ -132,7 +139,12 @@ export const PrepareReleaseNotes: FC<Props> = ({ prs }) => {
<h2>
Fixes (<EuiCode>release_note:fix</EuiCode>)
</h2>
<GroupedPrList groupedPrs={fixesPr} groups={config.areas} keyPrefix="fixes" />
<GroupedPrList
groupedPrs={fixesPr}
groups={config.areas}
keyPrefix="fixes"
version={version}
/>
</>
)}
</EuiText>
Expand Down
2 changes: 1 addition & 1 deletion src/pages/release-notes/release-notes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ export const ReleaseNotes: FC<Props> = ({
</>
)}
{step === 'prepare' ? (
<PrepareReleaseNotes prs={prs} />
<PrepareReleaseNotes prs={prs} version={version} />
) : (
<ReleaseNoteOutput prs={prs} version={version} />
)}
Expand Down