diff --git a/web/src/components/BranchProtection/BranchProtectionForm/BranchProtectionForm.tsx b/web/src/components/BranchProtection/BranchProtectionForm/BranchProtectionForm.tsx
index 629d106d5..7b163f8b6 100644
--- a/web/src/components/BranchProtection/BranchProtectionForm/BranchProtectionForm.tsx
+++ b/web/src/components/BranchProtection/BranchProtectionForm/BranchProtectionForm.tsx
@@ -166,6 +166,9 @@ const BranchProtectionForm = (props: {
const isRebasePresent = (rule.definition as ProtectionBranch)?.pullreq?.merge?.strategies_allowed?.includes(
MergeStrategy.REBASE
)
+ const isFFMergePresent = (rule.definition as ProtectionBranch)?.pullreq?.merge?.strategies_allowed?.includes(
+ MergeStrategy.FAST_FORWARD
+ )
// List of strings to be included in the final array
const includeList = (rule?.pattern as ProtectionPattern)?.include ?? []
const excludeList = (rule?.pattern as ProtectionPattern)?.exclude ?? []
@@ -201,6 +204,7 @@ const BranchProtectionForm = (props: {
mergeCommit: isMergePresent,
squashMerge: isSquashPresent,
rebaseMerge: isRebasePresent,
+ fastForwardMerge: isFFMergePresent,
autoDelete: (rule.definition as ProtectionBranch)?.pullreq?.merge?.delete_branch,
blockBranchCreation: (rule.definition as ProtectionBranch)?.lifecycle?.create_forbidden,
blockBranchUpdate:
@@ -244,7 +248,8 @@ const BranchProtectionForm = (props: {
const stratArray = [
formData.squashMerge && MergeStrategy.SQUASH,
formData.rebaseMerge && MergeStrategy.REBASE,
- formData.mergeCommit && MergeStrategy.MERGE
+ formData.mergeCommit && MergeStrategy.MERGE,
+ formData.fastForwardMerge && MergeStrategy.FAST_FORWARD
].filter(Boolean) as EnumMergeMethod[]
const includeArray =
formData?.targetList?.filter(([type]) => type === 'include').map(([, value]) => value) ?? []
diff --git a/web/src/components/BranchProtection/BranchProtectionForm/ProtectionRulesForm/ProtectionRulesForm.tsx b/web/src/components/BranchProtection/BranchProtectionForm/ProtectionRulesForm/ProtectionRulesForm.tsx
index 07f6ebb2e..00aa2c19e 100644
--- a/web/src/components/BranchProtection/BranchProtectionForm/ProtectionRulesForm/ProtectionRulesForm.tsx
+++ b/web/src/components/BranchProtection/BranchProtectionForm/ProtectionRulesForm/ProtectionRulesForm.tsx
@@ -269,6 +269,11 @@ const ProtectionRulesForm = (props: {
+
)}
diff --git a/web/src/framework/strings/stringTypes.ts b/web/src/framework/strings/stringTypes.ts
index 44200474f..a30bc9bd5 100644
--- a/web/src/framework/strings/stringTypes.ts
+++ b/web/src/framework/strings/stringTypes.ts
@@ -424,6 +424,7 @@ export interface StringsMap {
failedToFetchFileContent: string
failedToImportSpace: string
failedToSavePipeline: string
+ fastForwardMerge: string
featureRoadmap: string
fileDeleted: string
fileTooLarge: string
@@ -801,6 +802,8 @@ export interface StringsMap {
'pr.mergeOptions.createAMergeCommit': string
'pr.mergeOptions.createMergeCommit': string
'pr.mergeOptions.createMergeCommitDesc': string
+ 'pr.mergeOptions.fastForwardMerge': string
+ 'pr.mergeOptions.fastForwardMergeDesc': string
'pr.mergeOptions.rebaseAndMerge': string
'pr.mergeOptions.rebaseAndMergeDesc': string
'pr.mergeOptions.squashAndMerge': string
@@ -825,6 +828,7 @@ export interface StringsMap {
'pr.prStateChanged': string
'pr.prStateChangedDraft': string
'pr.readyForReview': string
+ 'pr.rebaseMergePossible': string
'pr.removeSuggestion': string
'pr.requestSubmitted': string
'pr.requestedChanges': string
@@ -995,6 +999,7 @@ export interface StringsMap {
'securitySettings.vulnerabilityScanning': string
'securitySettings.vulnerabilityScanningDesc': string
seeNMoreMatches: string
+ selectAuthor: string
selectBranchPlaceHolder: string
selectLanguagePlaceholder: string
selectMergeStrat: string
diff --git a/web/src/i18n/strings.en.yaml b/web/src/i18n/strings.en.yaml
index 254e29811..72e52364f 100644
--- a/web/src/i18n/strings.en.yaml
+++ b/web/src/i18n/strings.en.yaml
@@ -302,6 +302,7 @@ pr:
reviewChanges: Review changes
mergePR: Merge pull request
branchHasNoConflicts: Pull request can be merged
+ rebaseMergePossible: Pull request can be merged after rebase
checkingToMerge: Checking for ability to merge automatically...
prCanBeMerged: Mergeing can be performed automatically.
enterDesc: Enter description here
@@ -341,6 +342,8 @@ pr:
createMergeCommitDesc: All commits from this branch will be added to the base branch via a merge commit.
rebaseAndMerge: Rebase and merge
rebaseAndMergeDesc: All commits from this branch will be rebased and added to the base branch.
+ fastForwardMerge: Fast-forward merge
+ fastForwardMergeDesc: All commits from this branch will be added to the base branch without a merge commit. Rebase may be required.
close: Close pull request
closeDesc: Close this pull request. You can still re-open the request after closing.
createAMergeCommit: Create a merge commit
@@ -539,6 +542,7 @@ zoomIn: Zoom In
zoomOut: Zoom Out
checks: Checks
blameCommitLine: '{author} committed {timestamp}'
+selectAuthor: Select Author
tooltipRepoEdit: You are not authorized to {PERMS}
missingPerms: 'You are missing the following permission:'
createRepoPerms: 'Create / Edit Repository'
@@ -964,6 +968,7 @@ setting: Setting
mergeCommit: Merge commit
squashMerge: Squash and merge
rebaseMerge: Rebase and merge
+fastForwardMerge: Fast-forward merge
Enable: Enable
imageUpload:
title: Upload attachment
diff --git a/web/src/pages/PullRequest/Conversation/PullRequestActionsBox/InlineMergeBox.tsx b/web/src/pages/PullRequest/Conversation/PullRequestActionsBox/InlineMergeBox.tsx
index d1a0550ab..9875e4c06 100644
--- a/web/src/pages/PullRequest/Conversation/PullRequestActionsBox/InlineMergeBox.tsx
+++ b/web/src/pages/PullRequest/Conversation/PullRequestActionsBox/InlineMergeBox.tsx
@@ -27,6 +27,7 @@ import { MergeStrategy } from 'utils/GitUtils'
import mergeVideo from '../../../../videos/merge.mp4'
import squashVideo from '../../../../videos/squash.mp4'
import rebaseVideo from '../../../../videos/rebase.mp4'
+import fastForward from '../../../../videos/fastForward.mp4'
import css from './PullRequestActionsBox.module.scss'
interface InlineMergeBoxProps {
@@ -96,6 +97,8 @@ const InlineMergeBox = (props: InlineMergeBoxProps) => {
) : mergeOption.method === MergeStrategy.SQUASH ? (
+ ) : mergeOption.method === MergeStrategy.FAST_FORWARD ? (
+
) : (
)}
@@ -142,11 +145,12 @@ const InlineMergeBox = (props: InlineMergeBoxProps) => {
{(mergeOption.method === MergeStrategy.SQUASH || mergeOption.method === MergeStrategy.MERGE) && (
)}
- {mergeOption.method !== MergeStrategy.REBASE && (
-
- )}
+ {mergeOption.method !== MergeStrategy.REBASE &&
+ mergeOption.method !== MergeStrategy.FAST_FORWARD && (
+
+ )}
)
}}
diff --git a/web/src/pages/PullRequest/Conversation/PullRequestActionsBox/PullRequestActionsBox.module.scss b/web/src/pages/PullRequest/Conversation/PullRequestActionsBox/PullRequestActionsBox.module.scss
index c9473be50..4db375552 100644
--- a/web/src/pages/PullRequest/Conversation/PullRequestActionsBox/PullRequestActionsBox.module.scss
+++ b/web/src/pages/PullRequest/Conversation/PullRequestActionsBox/PullRequestActionsBox.module.scss
@@ -89,6 +89,8 @@
&.merged {
font-weight: unset !important;
color: var(--purple-700) !important;
+ white-space: nowrap !important;
+ font-size: 14px !important;
}
&.draft {
@@ -108,7 +110,7 @@
.boldText {
color: var(--purple-700) !important;
font-weight: 600 !important;
- font-size: 16px !important;
+ font-size: 14px !important;
line-height: 24px !important;
}
.widthContainer {
diff --git a/web/src/pages/PullRequest/Conversation/PullRequestActionsBox/PullRequestActionsBox.tsx b/web/src/pages/PullRequest/Conversation/PullRequestActionsBox/PullRequestActionsBox.tsx
index 37169cf3c..cb747d95b 100644
--- a/web/src/pages/PullRequest/Conversation/PullRequestActionsBox/PullRequestActionsBox.tsx
+++ b/web/src/pages/PullRequest/Conversation/PullRequestActionsBox/PullRequestActionsBox.tsx
@@ -30,17 +30,18 @@ import {
useToaster
} from '@harnessio/uicore'
import { Icon } from '@harnessio/icons'
-import { Color } from '@harnessio/design-system'
+import { Color, FontVariation } from '@harnessio/design-system'
import { MutateMethod, useMutate } from 'restful-react'
import { Case, Else, Match, Render, Truthy } from 'react-jsx-match'
import { Menu, PopoverPosition, Icon as BIcon } from '@blueprintjs/core'
import cx from 'classnames'
-import ReactTimeago from 'react-timeago'
+import { defaultTo } from 'lodash-es'
import type {
CreateBranchPathParams,
DeletePullReqSourceBranchQueryParams,
OpenapiCreateBranchRequest,
OpenapiStatePullReqRequest,
+ RebaseBranchRequestBody,
TypesListCommitResponse,
TypesPullReq,
TypesRuleViolations
@@ -58,9 +59,9 @@ import {
permissionProps
} from 'utils/Utils'
import { OptionsMenuButton } from 'components/OptionsMenuButton/OptionsMenuButton'
-import { UserPreference, useUserPreference } from 'hooks/useUserPreference'
import { useGetRepositoryMetadata } from 'hooks/useGetRepositoryMetadata'
import { PullReqSuggestionsBatch } from 'components/PullReqSuggestionsBatch/PullReqSuggestionsBatch'
+import { TimePopoverWithLocal } from 'utils/timePopoverLocal/TimePopoverWithLocal'
import { BranchActionsButton } from '../PullRequestOverviewPanel/sections/BranchActionsSection'
import InlineMergeBox from './InlineMergeBox'
import css from './PullRequestActionsBox.module.scss'
@@ -83,6 +84,9 @@ export interface PullRequestActionsBoxProps extends Pick>
setShowRestoreBranchButton: React.Dispatch>
isSourceBranchDeleted: boolean
+ mergeOption: PRMergeOption
+ setMergeOption: (val: PRMergeOption) => void
+ rebasePossible: boolean
}
export const PullRequestActionsBox: React.FC = ({
@@ -102,10 +106,13 @@ export const PullRequestActionsBox: React.FC = ({
showDeleteBranchButton,
setShowRestoreBranchButton,
setShowDeleteBranchButton,
- isSourceBranchDeleted
+ isSourceBranchDeleted,
+ mergeOption,
+ setMergeOption,
+ rebasePossible
}) => {
const { getString } = useStrings()
- const { showError } = useToaster()
+ const { showSuccess, showError } = useToaster()
const inlineMergeRef = useRef(null)
const { hooks, standalone } = useAppContext()
const space = useGetSpaceParam()
@@ -122,6 +129,19 @@ export const PullRequestActionsBox: React.FC = ({
verb: 'POST',
path: `/api/v1/repos/${repoMetadata.path}/+/pullreq/${pullReqMetadata.number}/state`
})
+ const { mutate: rebase } = useMutate({
+ verb: 'POST',
+ path: `/api/v1/repos/${repoMetadata.path}/+/rebase`
+ })
+
+ const rebaseRequestPayload = {
+ base_branch: pullReqMetadata.target_branch,
+ bypass_rules: true,
+ dry_run_rules: false,
+ head_branch: pullReqMetadata.source_branch,
+ head_commit_sha: pullReqMetadata.source_sha
+ }
+
const mergeable = useMemo(() => pullReqMetadata.merge_check_status === MergeCheckStatus.MERGEABLE, [pullReqMetadata])
const isClosed = pullReqMetadata.state === PullRequestState.CLOSED
const isOpen = pullReqMetadata.state === PullRequestState.OPEN
@@ -193,11 +213,12 @@ export const PullRequestActionsBox: React.FC = ({
} // eslint-disable-next-line react-hooks/exhaustive-deps
}, [onPRStateChanged, isMerged, isClosed, pullReqMetadata?.source_sha])
- const mergeOptions = useMemo(() => getMergeOptions(getString, mergeable).slice(0, 3), [mergeable])
+ const mergeOptions = useMemo(() => getMergeOptions(getString, mergeable).slice(0, 4), [mergeable])
const [allowedStrats, setAllowedStrats] = useState([
mergeOptions[0].method,
mergeOptions[1].method,
- mergeOptions[2].method
+ mergeOptions[2].method,
+ mergeOptions[3].method
])
const draftOptions: PRDraftOption[] = [
{
@@ -212,11 +233,6 @@ export const PullRequestActionsBox: React.FC = ({
}
]
const [showInlineMergeContainer, setShowInlineMergeContainer] = useState(false)
- const [mergeOption, setMergeOption] = useUserPreference(
- UserPreference.PULL_REQUEST_MERGE_STRATEGY,
- mergeOptions[0],
- option => option.method !== 'close'
- )
useEffect(() => {
if (allowedStrats) {
@@ -283,6 +299,7 @@ export const PullRequestActionsBox: React.FC = ({
className={cx(css.main, {
[css.primary]: !PRStateLoading,
[css.error]: mergeable === false && !unchecked && !isClosed && !isDraft,
+ [css.error]: mergeOption.method === MergeStrategy.FAST_FORWARD && rebasePossible,
[css.unchecked]: unchecked,
[css.closed]: isClosed,
[css.draft]: isDraft,
@@ -302,6 +319,7 @@ export const PullRequestActionsBox: React.FC = ({
[css.draft]: isDraft,
[css.closed]: isClosed,
[css.unmergeable]: mergeable === false && isOpen,
+ [css.unmergeable]: mergeOption.method === MergeStrategy.FAST_FORWARD && rebasePossible && isOpen,
[css.ruleViolate]: ruleViolation && !isClosed
})}>
{getString(
@@ -315,6 +333,8 @@ export const PullRequestActionsBox: React.FC = ({
? 'branchProtection.prFailedText'
: ruleViolation
? 'branchProtection.prFailedText'
+ : mergeOption.method === MergeStrategy.FAST_FORWARD && rebasePossible
+ ? 'branchProtection.prFailedText'
: 'pr.branchHasNoConflicts'
)}
@@ -473,7 +493,9 @@ export const PullRequestActionsBox: React.FC = ({
@@ -506,7 +528,25 @@ export const PullRequestActionsBox: React.FC = ({
})
.catch(exception => showError(getErrorMessage(exception)))
}
- }
+ },
+ ...(rebasePossible
+ ? [
+ {
+ hasIcon: true,
+ iconName: 'code-pull',
+ text: getString('rebase'),
+ onClick: () =>
+ rebase(rebaseRequestPayload)
+ .then(() => {
+ showSuccess(getString('updatedBranchMessageRebase'))
+ setTimeout(() => {
+ refetchActivities()
+ }, 1000)
+ })
+ .catch(err => showError(getErrorMessage(err)))
+ }
+ ]
+ : [])
]}
tooltipProps={{
interactionKind: 'click',
@@ -593,7 +633,15 @@ const MergeInfo: React.FC<{
),
- time:
+ time: (
+
+ )
}}
/>
diff --git a/web/src/pages/PullRequest/Conversation/PullRequestOverviewPanel/PullRequestOverviewPanel.tsx b/web/src/pages/PullRequest/Conversation/PullRequestOverviewPanel/PullRequestOverviewPanel.tsx
index 62d750cdb..59c2bb23d 100644
--- a/web/src/pages/PullRequest/Conversation/PullRequestOverviewPanel/PullRequestOverviewPanel.tsx
+++ b/web/src/pages/PullRequest/Conversation/PullRequestOverviewPanel/PullRequestOverviewPanel.tsx
@@ -30,15 +30,17 @@ import type {
TypesBranch
} from 'services/code'
import {
+ PRMergeOption,
PanelSectionOutletPosition,
extractSpecificViolations,
getMergeOptions
} from 'pages/PullRequest/PullRequestUtils'
import { MergeCheckStatus, extractInfoFromRuleViolationArr } from 'utils/Utils'
-import { PullRequestState, dryMerge } from 'utils/GitUtils'
+import { MergeStrategy, PullRequestState, dryMerge } from 'utils/GitUtils'
import { useStrings } from 'framework/strings'
import type { PRChecksDecisionResult } from 'hooks/usePRChecksDecision'
import { useGetRepositoryMetadata } from 'hooks/useGetRepositoryMetadata'
+import { UserPreference, useUserPreference } from 'hooks/useUserPreference'
import { PullRequestActionsBox } from '../PullRequestActionsBox/PullRequestActionsBox'
import PullRequestPanelSections from './PullRequestPanelSections'
import ChecksSection from './sections/ChecksSection'
@@ -241,6 +243,12 @@ const PullRequestOverviewPanel = (props: PullRequestOverviewPanelProps) => {
[pullReqMetadata]
)
+ const [mergeOption, setMergeOption] = useUserPreference(
+ UserPreference.PULL_REQUEST_MERGE_STRATEGY,
+ mergeOptions[0],
+ option => option.method !== 'close'
+ )
+
return (
@@ -264,6 +272,9 @@ const PullRequestOverviewPanel = (props: PullRequestOverviewPanelProps) => {
setShowDeleteBranchButton={setShowDeleteBranchButton}
setShowRestoreBranchButton={setShowRestoreBranchButton}
isSourceBranchDeleted={isSourceBranchDeleted}
+ mergeOption={mergeOption}
+ setMergeOption={setMergeOption}
+ rebasePossible={rebasePossible}
/>
{!isClosed ? (
{
),
[PanelSectionOutletPosition.REBASE_SOURCE_BRANCH]: rebasePossible &&
!mergeLoading &&
- !conflictingFiles?.length && (
+ !conflictingFiles?.length &&
+ mergeOption.method === MergeStrategy.FAST_FORWARD && (
{
diff --git a/web/src/pages/PullRequest/Conversation/PullRequestOverviewPanel/sections/RebaseSourceSection.tsx b/web/src/pages/PullRequest/Conversation/PullRequestOverviewPanel/sections/RebaseSourceSection.tsx
index c3c7ba432..ca988894c 100644
--- a/web/src/pages/PullRequest/Conversation/PullRequestOverviewPanel/sections/RebaseSourceSection.tsx
+++ b/web/src/pages/PullRequest/Conversation/PullRequestOverviewPanel/sections/RebaseSourceSection.tsx
@@ -33,7 +33,7 @@ import { GitRefLink } from 'components/GitRefLink/GitRefLink'
import { getErrorMessage, permissionProps } from 'utils/Utils'
import { useGetSpaceParam } from 'hooks/useGetSpaceParam'
import { useAppContext } from 'AppContext'
-import Fail from '../../../../../icons/code-fail-grey.svg?url'
+import FailRed from '../../../../../icons/code-fail.svg?url'
import css from '../PullRequestOverviewPanel.module.scss'
interface RebaseSourceSectionProps {
@@ -80,9 +80,9 @@ const RebaseSourceSection = (props: RebaseSourceSectionProps) => {
-
+
-
+
{getString('rebaseSource.title')}
diff --git a/web/src/pages/PullRequest/Conversation/SystemComment.tsx b/web/src/pages/PullRequest/Conversation/SystemComment.tsx
index 8255b88bf..f310bb28c 100644
--- a/web/src/pages/PullRequest/Conversation/SystemComment.tsx
+++ b/web/src/pages/PullRequest/Conversation/SystemComment.tsx
@@ -65,7 +65,7 @@ export const SystemComment: React.FC = ({ pullReqMetadata, c
-
+
= ({ pullReqMetadata, c
}
vars={{
user: {pullReqMetadata.merger?.display_name},
- source: {pullReqMetadata.source_branch},
- target: {pullReqMetadata.target_branch},
+ source: (
+
+ {pullReqMetadata.source_branch}
+
+ ),
+ target: (
+
+ {pullReqMetadata.target_branch}
+
+ ),
bypassed: (payload?.payload as MergePayload)?.rules_bypassed,
mergeSha: (
diff --git a/web/src/pages/PullRequest/PullRequestUtils.tsx b/web/src/pages/PullRequest/PullRequestUtils.tsx
index 25b01cb7b..3f42cb246 100644
--- a/web/src/pages/PullRequest/PullRequestUtils.tsx
+++ b/web/src/pages/PullRequest/PullRequestUtils.tsx
@@ -113,6 +113,14 @@ export const getMergeOptions = (getString: UseStringsReturn['getString'], mergea
label: getString('pr.mergeOptions.rebaseAndMerge'),
value: MergeStrategy.REBASE
},
+ {
+ method: MergeStrategy.FAST_FORWARD,
+ title: getString('pr.mergeOptions.fastForwardMerge'),
+ desc: getString('pr.mergeOptions.fastForwardMergeDesc'),
+ disabled: mergeable === false,
+ label: getString('pr.mergeOptions.fastForwardMerge'),
+ value: MergeStrategy.FAST_FORWARD
+ },
{
method: 'close',
title: getString('pr.mergeOptions.close'),
diff --git a/web/src/pages/PullRequests/PullRequestsContentHeader/PullRequestsContentHeader.tsx b/web/src/pages/PullRequests/PullRequestsContentHeader/PullRequestsContentHeader.tsx
index e054786fc..a7bf61e5e 100644
--- a/web/src/pages/PullRequests/PullRequestsContentHeader/PullRequestsContentHeader.tsx
+++ b/web/src/pages/PullRequests/PullRequestsContentHeader/PullRequestsContentHeader.tsx
@@ -209,7 +209,7 @@ export function PullRequestsContentHeader({
popoverClassName={css.branchDropdown}
icon="nav-user-profile"
iconProps={{ size: 16 }}
- placeholder="Select Authors"
+ placeholder={getString('selectAuthor')}
addClearBtn={true}
resetOnClose
resetOnSelect
diff --git a/web/src/services/code/index.tsx b/web/src/services/code/index.tsx
index 8ea7898b2..5f0ab56b3 100644
--- a/web/src/services/code/index.tsx
+++ b/web/src/services/code/index.tsx
@@ -116,7 +116,7 @@ export type EnumMembershipRole = 'contributor' | 'executor' | 'reader' | 'space_
export type EnumMergeCheckStatus = string
-export type EnumMergeMethod = 'merge' | 'rebase' | 'squash'
+export type EnumMergeMethod = 'fast-forward' | 'merge' | 'rebase' | 'squash'
export type EnumParentResourceType = 'space' | 'repo'
@@ -1156,9 +1156,12 @@ export type TypesGitspaceInstance = {
access_key?: string | null
access_key_ref?: string | null
access_type?: EnumGitspaceAccessType
+ active_time_ended?: number | null
+ active_time_started?: number | null
created?: number
identifier?: string
- last_used?: number
+ last_heartbeat?: number | null
+ last_used?: number | null
machine_user?: string | null
resource_usage?: string | null
space_path?: string
@@ -1475,6 +1478,9 @@ export interface TypesPullReqStats {
}
export interface TypesRebaseResponse {
+ already_ancestor?: boolean
+ conflict_files?: string[]
+ dry_run?: boolean
dry_run_rules?: boolean
new_head_branch_sha?: ShaSHA
rule_violations?: TypesRuleViolations[]
@@ -6240,6 +6246,7 @@ export interface RebaseBranchPathParams {
export interface RebaseBranchRequestBody {
base_branch?: string
bypass_rules?: boolean
+ dry_run?: boolean
dry_run_rules?: boolean
head_branch?: string
head_commit_sha?: ShaSHA
diff --git a/web/src/services/code/swagger.yaml b/web/src/services/code/swagger.yaml
index 9fa503ccf..fe49da6c2 100644
--- a/web/src/services/code/swagger.yaml
+++ b/web/src/services/code/swagger.yaml
@@ -6225,6 +6225,8 @@ paths:
type: string
bypass_rules:
type: boolean
+ dry_run:
+ type: boolean
dry_run_rules:
type: boolean
head_branch:
@@ -10540,6 +10542,7 @@ components:
type: string
EnumMergeMethod:
enum:
+ - fast-forward
- merge
- rebase
- squash
@@ -12408,11 +12411,21 @@ components:
type: string
access_type:
$ref: '#/components/schemas/EnumGitspaceAccessType'
+ active_time_ended:
+ nullable: true
+ type: integer
+ active_time_started:
+ nullable: true
+ type: integer
created:
type: integer
identifier:
type: string
+ last_heartbeat:
+ nullable: true
+ type: integer
last_used:
+ nullable: true
type: integer
machine_user:
nullable: true
@@ -13013,6 +13026,14 @@ components:
type: object
TypesRebaseResponse:
properties:
+ already_ancestor:
+ type: boolean
+ conflict_files:
+ items:
+ type: string
+ type: array
+ dry_run:
+ type: boolean
dry_run_rules:
type: boolean
new_head_branch_sha:
diff --git a/web/src/utils/GitUtils.ts b/web/src/utils/GitUtils.ts
index 1f854d91d..91f2af467 100644
--- a/web/src/utils/GitUtils.ts
+++ b/web/src/utils/GitUtils.ts
@@ -233,7 +233,8 @@ export const PullRequestFilterOption = {
export enum MergeStrategy {
MERGE = 'merge',
SQUASH = 'squash',
- REBASE = 'rebase'
+ REBASE = 'rebase',
+ FAST_FORWARD = 'fast-forward'
}
export const CodeIcon = {
diff --git a/web/src/utils/Utils.ts b/web/src/utils/Utils.ts
index d35603a39..a4727c61c 100644
--- a/web/src/utils/Utils.ts
+++ b/web/src/utils/Utils.ts
@@ -385,6 +385,7 @@ export type RulesFormPayload = {
mergeCommit?: boolean
squashMerge?: boolean
rebaseMerge?: boolean
+ fastForwardMerge?: boolean
autoDelete?: boolean
blockBranchCreation?: boolean
blockBranchDeletion?: boolean
diff --git a/web/src/videos/fastForward.mp4 b/web/src/videos/fastForward.mp4
new file mode 100644
index 000000000..31faa2525
Binary files /dev/null and b/web/src/videos/fastForward.mp4 differ