Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add pr-base-commit feature #6538

Merged
merged 29 commits into from
Apr 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
68abffa
Lint
yakov116 Nov 1, 2022
ac82965
Add behind count to update branch
yakov116 Nov 1, 2022
f1fe231
Lint
yakov116 Nov 1, 2022
3c3b1a3
Enable for enterprise
yakov116 Nov 1, 2022
cc751e9
Lint
yakov116 Nov 1, 2022
cc732b7
Move behind by up
yakov116 Nov 1, 2022
a12d36f
Merge commit 'cc732b79272f571f9f2a15eb77cdd41e84f1b097'
fregante Apr 17, 2023
daf892b
Move "Update" button to mergeability box
fregante Apr 17, 2023
e70c3fb
Activate button
fregante Apr 17, 2023
8a88724
Don't show when native exists
fregante Apr 17, 2023
4fa0bb3
Integrate in native "can be merged" row
fregante Apr 17, 2023
b87c979
Add one more test URL
fregante Apr 17, 2023
1dd76ae
Add draft PR URL
fregante Apr 17, 2023
ba54d80
Early return
fregante Apr 17, 2023
7b5cf03
Drop duplicate check
fregante Apr 17, 2023
c67860c
Add meta
fregante Apr 17, 2023
dfe482d
Merge remote-tracking branch 'origin/update-pr' into base-commit
fregante Apr 17, 2023
298265e
Yakov style; extracted
fregante Apr 17, 2023
b86f46f
Style optimization 1/?
fregante Apr 17, 2023
9a3f49d
Fix URL, it must compare the base commit to the latest base branch co…
fregante Apr 17, 2023
8269685
Lint
fregante Apr 17, 2023
61dd9c5
Extract into its own feature
fregante Apr 17, 2023
d08e8d9
/2
fregante Apr 17, 2023
6af48fb
Lint
fregante Apr 17, 2023
359a2cc
Merge remote-tracking branch 'origin/main' into base-commit
fregante Apr 26, 2023
364507e
Flip ahead/behind; drop GHE support
fregante Apr 26, 2023
04541e6
Add to readme; finalize copy
fregante Apr 26, 2023
b4fe378
Fix `linkifyCommit`
fregante Apr 26, 2023
d5ab97c
Lint
fregante Apr 26, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 3 additions & 2 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,8 @@ GitHub Enterprise is also supported: [How to enable it](https://fregante.github.
<p><img src="https://user-images.githubusercontent.com/1402241/54978791-45906080-4fdc-11e9-8fe1-45374f8ff636.png">
<tr>
<th width="50%">
<p><a title="reactions-avatars"></a> Adds reaction avatars showing <i>who</i> reacted to a comment
<p><img src="https://user-images.githubusercontent.com/1402241/130341871-6a0d69f4-8d0c-4882-a5ed-aac9b7613b0a.png">
<p><a title="pr-base-commit"></a> Shows how far behind a PR head branch is + tells you its base commit
<p><img src="https://user-images.githubusercontent.com/1402241/234492651-b54bf9ba-c218-4a30-bed4-f85a7f037297.png">
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Final look:

reaction-avatars downgraded

<th width="50%">
<p><a title="conversation-activity-filter"></a> Lets you hide every event except comments or unresolved comments in issues and PRs
<p><img src="https://user-images.githubusercontent.com/1402241/109592127-5f922200-7ad4-11eb-8dfa-1d80fb28e70e.png">
Expand Down Expand Up @@ -212,6 +212,7 @@ Thanks for contributing! 🦋🙌

### Reading comments

- [](# "reactions-avatars") 🔥 [Adds reaction avatars showing _who_ reacted to a comment](https://user-images.githubusercontent.com/1402241/234492651-b54bf9ba-c218-4a30-bed4-f85a7f037297.png)
- [](# "embed-gist-inline") [Embeds short gists when linked in comments on their own lines.](https://user-images.githubusercontent.com/1402241/152117903-80d784d5-4f43-4786-bc4c-d4993aec5c79.png)
- [](# "comments-time-machine-links") Adds links to [browse the repository](https://user-images.githubusercontent.com/1402241/56450896-68076680-635b-11e9-8b24-ebd11cc4e655.png) and [linked files](https://user-images.githubusercontent.com/1402241/56450895-68076680-635b-11e9-86b4-b6c2f3745d51.png) at the time of each comment.
- [](# "show-names") [Adds the real name of users by their usernames.](https://user-images.githubusercontent.com/1402241/62075835-5f82ce00-b270-11e9-91eb-4680b70cb3cb.png)
Expand Down
85 changes: 85 additions & 0 deletions source/features/pr-base-commit.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import React from 'dom-chef';
import select from 'select-dom';

import * as pageDetect from 'github-url-detection';

import features from '../feature-manager';
import observe from '../helpers/selector-observer';
import * as api from '../github-helpers/api';
import {getBranches} from '../github-helpers/pr-branches';
import getPrInfo, {PullRequestInfo} from '../github-helpers/get-pr-info';
import pluralize from '../helpers/pluralize';
import {buildRepoURL} from '../github-helpers';
import {linkifyCommit} from '../github-helpers/dom-formatters';
import {removeTextNodeContaining} from '../helpers/dom-utils';

function getBaseCommitNotice(prInfo: PullRequestInfo): JSX.Element {
const {base} = getBranches();
const commit = linkifyCommit(prInfo.baseRefOid);
const count = pluralize(prInfo.behindBy, '$$ commit');
const countLink = (
<a href={buildRepoURL('compare', `${prInfo.baseRefOid.slice(0, 8)}...${base.branch}`)}>
{count}
</a>
);
return (
<>It’s {countLink} behind (base commit: {commit})</>
);
}

async function addInfo(statusMeta: Element): Promise<void> {
// Selector copied from GitHub. Don't @ me
// This excludes hidden ".status-meta" items without adding this longass selector to the observer
// Added: .rgh-update-pr-from-base-branch-row
if (!statusMeta.closest('.merge-pr.is-merging .merging-body, .merge-pr.is-merging .merge-commit-author-email-info, .merge-pr.is-merging-solo .merging-body, .merge-pr.is-merging-jump .merging-body, .merge-pr.is-merging-group .merging-body, .merge-pr.is-rebasing .rebasing-body, .merge-pr.is-squashing .squashing-body, .merge-pr.is-squashing .squash-commit-author-email-info, .merge-pr.is-merging .branch-action-state-error-if-merging .merging-body-merge-warning, .rgh-update-pr-from-base-branch-row')) {
return;
}

const {base} = getBranches();
const prInfo = await getPrInfo(base.relative);
if (!prInfo.needsUpdate) {
return;
}

const previousMessage = statusMeta.firstChild!; // Extract now because it won't be the first child anymore
statusMeta.prepend(getBaseCommitNotice(prInfo));
removeTextNodeContaining(previousMessage, 'Merging can be performed automatically.');
}

async function init(signal: AbortSignal): Promise<false | void> {
await api.expectToken();

observe('.branch-action-item .status-meta', addInfo, {signal});
}

void features.add(import.meta.url, {
include: [
pageDetect.isPRConversation,
],
exclude: [
pageDetect.isClosedPR,
() => select('.head-ref')!.title === 'This repository has been deleted',
],
awaitDomReady: true, // DOM-based exclusions
init,
});

/*
Test URLs

PR without conflicts
https://github.com/refined-github/sandbox/pull/60

Draft PR without conflicts
https://github.com/refined-github/sandbox/pull/61

Native "Update branch" button
(pick a conflict-free PR from https://github.com/refined-github/refined-github/pulls?q=is%3Apr+is%3Aopen+sort%3Acreated-asc)

Native "Resolve conflicts" button
https://github.com/refined-github/sandbox/pull/9

Cross-repo PR with long branch names
https://github.com/refined-github/sandbox/pull/13

*/
9 changes: 5 additions & 4 deletions source/features/update-pr-from-base-branch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import observe from '../helpers/selector-observer';
import * as api from '../github-helpers/api';
import {getBranches} from '../github-helpers/pr-branches';
import getPrInfo from '../github-helpers/get-pr-info';
import {getConversationNumber} from '../github-helpers';
import showToast from '../github-helpers/toast';
import {getConversationNumber} from '../github-helpers';
import createMergeabilityRow from '../github-widgets/mergeability-row';
import selectHas from '../helpers/select-has';

Expand Down Expand Up @@ -60,9 +60,9 @@ async function addButton(mergeBar: Element): Promise<void> {
return;
}

const {base, head} = getBranches();
const prInfo = await getPrInfo(base.relative, head.relative);
if (!prInfo?.viewerCanEditFiles || prInfo.mergeable === 'CONFLICTING') {
const {base} = getBranches();
const prInfo = await getPrInfo(base.relative);
if (!prInfo.needsUpdate || !prInfo.viewerCanEditFiles || prInfo.mergeable === 'CONFLICTING') {
return;
}

Expand All @@ -82,6 +82,7 @@ async function addButton(mergeBar: Element): Promise<void> {

// The PR is still a draft
mergeBar.before(createMergeabilityRow({
className: 'rgh-update-pr-from-base-branch-row',
action: createButton(),
icon: <CheckIcon/>,
iconClass: 'completeness-indicator-success',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import React from 'dom-chef';
import select from 'select-dom';
import zipTextNodes from 'zip-text-nodes';
import {applyToLink} from 'shorten-repo-url';
Expand All @@ -6,6 +7,7 @@ import linkifyIssuesCore from 'linkify-issues';

import getTextNodes from '../helpers/get-text-nodes';
import parseBackticksCore from './parse-backticks';
import {buildRepoURL} from '.';

// Shared class necessary to avoid also shortening the links
export const linkifiedURLClass = 'rgh-linkified-code';
Expand Down Expand Up @@ -93,3 +95,19 @@ export function parseBackticks(element: Element): void {
}
}
}

export function linkifyCommit(sha: string): JSX.Element {
// Data attributes copied from the commit in https://github.com/refined-github/github-url-detection/releases/tag/v7.1.2
return (
<code>
<a
className="Link--secondary"
href={buildRepoURL('commit', sha)}
data-hovercard-type="commit"
data-hovercard-url={buildRepoURL('commit', sha, 'hovercard')}
>
{sha.slice(0, 7)}
</a>
</code>
);
}
48 changes: 19 additions & 29 deletions source/github-helpers/get-pr-info.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,17 @@
import * as pageDetect from 'github-url-detection';

import * as api from './api';
import {getConversationNumber} from '.';

type PullRequestInfo = {
// TODO: Use this for `restore-file` when GHE supports `compare`
export type PullRequestInfo = {
// TODO: Use this for `restore-file`
baseRefOid: string;
// https://docs.github.com/en/graphql/reference/enums#mergeablestate
mergeable: 'CONFLICTING' | 'MERGEABLE' | 'UNKNOWN';
viewerCanEditFiles: boolean;
needsUpdate: boolean;
behindBy: number;
};

export default async function getPrInfo(base: string, head: string, number = getConversationNumber()!): Promise<PullRequestInfo | undefined> {
if (pageDetect.isEnterprise()) {
const {repository} = await api.v4(`
repository() {
pullRequest(number: ${number}) {
mergeable
viewerCanEditFiles
}
}
`);

const compare = await api.v3(`compare/${base}...${head}?page=10000`); // `page=10000` avoids fetching any commit information, which is heavy
if (compare.status !== 'diverged') {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's been 6 months. Dropping

return;
}

return repository.pullRequest;
}

export default async function getPrInfo(base: string, number = getConversationNumber()!): Promise<PullRequestInfo> {
const {repository} = await api.v4(`
repository() {
pullRequest(number: ${number}) {
Expand All @@ -39,17 +21,25 @@ export default async function getPrInfo(base: string, head: string, number = get
headRef {
compare(headRef: "${base}") {
status
behindBy
aheadBy
}
}
}
}
`);

if (repository.pullRequest.headRef.compare.status !== 'DIVERGED') {
return;
}

return repository.pullRequest;
const {
baseRefOid,
mergeable,
viewerCanEditFiles,
headRef,
} = repository.pullRequest;
return {
baseRefOid,
mergeable,
viewerCanEditFiles,
// The comparison in the API is base -> head, so it must be flipped
behindBy: headRef.compare.aheadBy,
needsUpdate: headRef.compare.status === 'DIVERGED',
};
}
8 changes: 5 additions & 3 deletions source/github-widgets/mergeability-row.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,21 @@ type MergeabilityRowProps = {
action?: JSX.Element;
icon: JSX.Element;
iconClass?: string;
heading: string;
meta?: string;
heading: JSX.Element | string;
meta?: JSX.Element | string;
className?: string;
};

export default function createMergeabilityRow({
className = '',
action,
icon,
iconClass = '',
heading,
meta,
}: MergeabilityRowProps): JSX.Element {
return (
<div className="branch-action-item">
<div className={`branch-action-item ${className}`}>
<div
className="branch-action-btn float-right js-immediate-updates js-needs-timeline-marker-header"
>
Expand Down
1 change: 1 addition & 0 deletions source/refined-github.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,3 +214,4 @@ import './features/netiquette';
import './features/rgh-netiquette';
import './features/small-user-avatars';
import './features/releases-dropdown';
import './features/pr-base-commit';