diff --git a/.changeset/gold-rice-cry.md b/.changeset/gold-rice-cry.md new file mode 100644 index 00000000..2193eca8 --- /dev/null +++ b/.changeset/gold-rice-cry.md @@ -0,0 +1,5 @@ +--- +"changesets-gitlab": minor +--- + +feat: add optional INPUT_MERGE_WHEN_PIPELINE_SUCCEEDS, INPUT_SQUASH, and INPUT_SQUASH_COMMIT_MESSAGE inputs to support auto-merge and squash settings for created merge requests diff --git a/README.md b/README.md index 378a2dab..a931ac09 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,9 @@ GitLab CI cli for [changesets](https://github.com/atlassian/changesets) like its - `INPUT_PUBLISHED` - Command executed after published - `INPUT_ONLY_CHANGESETS` - Command executed on only changesets detected - `INPUT_REMOVE_SOURCE_BRANCH` - Enables the merge request "Delete source branch" checkbox. Default false. +- `INPUT_MERGE_WHEN_PIPELINE_SUCCEEDS` - Sets auto-merge on the created merge request (merge when all checks pass). If not set, no changes are made. +- `INPUT_SQUASH` - Enables or disables squash commits for the merge request. If not set, no changes are made. +- `INPUT_SQUASH_COMMIT_MESSAGE` - The optional squash commit message used when squash is enabled. - `INPUT_TARGET_BRANCH` -> The merge request target branch. Defaults to current branch - `INPUT_CREATE_GITLAB_RELEASES` - A boolean value to indicate whether to create Gitlab releases after publish or not. Default true. - `INPUT_LABELS` - A comma separated string of labels to be added to the version package Gitlab Merge request diff --git a/src/main.ts b/src/main.ts index 5eabf022..c17312e8 100644 --- a/src/main.ts +++ b/src/main.ts @@ -13,6 +13,7 @@ import type { MainCommandOptions } from './types.js' import { execSync, FALSY_VALUES, + getOptionalBooleanInput, getOptionalInput, getUsername, TRUTHY_VALUES, @@ -108,7 +109,12 @@ export const main = async ({ mrTitle: getOptionalInput('title'), mrTargetBranch: getOptionalInput('target_branch'), commitMessage: getOptionalInput('commit'), - removeSourceBranch: getInput('remove_source_branch') === 'true', + removeSourceBranch: getOptionalBooleanInput('remove_source_branch'), + mergeWhenPipelineSucceeds: getOptionalBooleanInput( + 'merge_when_pipeline_succeeds', + ), + squash: getOptionalBooleanInput('squash'), + squashCommitMessage: getOptionalInput('squash_commit_message'), hasPublishScript, }) if (onlyChangesets) { diff --git a/src/run.ts b/src/run.ts index 7a41e5b6..f1a23ca6 100644 --- a/src/run.ts +++ b/src/run.ts @@ -2,7 +2,12 @@ import fs from 'node:fs/promises' import path from 'node:path' import { exec } from '@actions/exec' -import type { Gitlab } from '@gitbeaker/core' +import type { + Gitlab, + MergeRequestSchema, + EditMergeRequestOptions, + AcceptMergeRequestOptions, +} from '@gitbeaker/core' import type { Package } from '@manypkg/get-packages' import { getPackages } from '@manypkg/get-packages' import pLimit from 'p-limit' @@ -207,6 +212,9 @@ export interface VersionOptions { cwd?: string mrTitle?: string removeSourceBranch?: boolean + mergeWhenPipelineSucceeds?: boolean + squash?: boolean + squashCommitMessage?: string mrTargetBranch?: string commitMessage?: string hasPublishScript?: boolean @@ -220,6 +228,9 @@ export async function runVersion({ mrTargetBranch = context.ref, commitMessage = 'Version Packages', removeSourceBranch = false, + mergeWhenPipelineSucceeds, + squash, + squashCommitMessage, hasPublishScript = false, }: VersionOptions) { const currentBranch = context.ref @@ -322,28 +333,59 @@ ${ perPage: 1, }) console.log(JSON.stringify(searchResult, null, 2)) + + let mergeRequest: MergeRequestSchema + const mergeRequestOptions: EditMergeRequestOptions = { + description: await mrBodyPromise, + removeSourceBranch, + labels, + squash, + } if (searchResult.length === 0) { console.log( `creating merge request from ${versionBranch} to ${mrTargetBranch}.`, ) - await api.MergeRequests.create( + mergeRequest = await api.MergeRequests.create( context.projectId, versionBranch, mrTargetBranch, finalMrTitle, - { - description: await mrBodyPromise, - removeSourceBranch, - labels, - }, + mergeRequestOptions, ) } else { console.log(`updating found merge request !${searchResult[0].iid}`) - await api.MergeRequests.edit(context.projectId, searchResult[0].iid, { - title: finalMrTitle, - description: await mrBodyPromise, - removeSourceBranch, - labels, - }) + mergeRequestOptions.title = finalMrTitle + mergeRequest = await api.MergeRequests.edit( + context.projectId, + searchResult[0].iid, + mergeRequestOptions, + ) + } + + const acceptRequest: AcceptMergeRequestOptions = {} + if ( + mergeWhenPipelineSucceeds !== undefined && + mergeRequest.merge_when_pipeline_succeeds !== mergeWhenPipelineSucceeds + ) { + acceptRequest.mergeWhenPipelineSucceeds = mergeWhenPipelineSucceeds + } + if ( + squash === true && + squashCommitMessage !== undefined && + mergeRequest.squash_commit_message !== squashCommitMessage + ) { + acceptRequest.squashCommitMessage = squashCommitMessage + } + + if (Object.keys(acceptRequest).length > 0) { + console.log( + `updating merge request !${mergeRequest.iid} with options:`, + acceptRequest, + ) + await api.MergeRequests.accept( + context.projectId, + mergeRequest.iid, + acceptRequest, + ) } } diff --git a/src/utils.ts b/src/utils.ts index cabea43b..1003f44f 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -159,7 +159,21 @@ export const execSync = (command: string) => // eslint-disable-next-line sonarjs/os-command execSync_(command, { stdio: 'inherit' }) +export const FALSY_VALUES = new Set(['false', '0']) + +export const TRUTHY_VALUES = new Set(['true', '1']) + export const getOptionalInput = (name: string) => getInput(name) || undefined +export const getOptionalBooleanInput = (name: string): boolean | undefined => { + const input = getInput(name) + if (TRUTHY_VALUES.has(input)) { + return true + } + if (FALSY_VALUES.has(input)) { + return false + } + return undefined +} // eslint-disable-next-line sonarjs/function-return-type export const getUsername = (api: Gitlab) => { @@ -172,10 +186,6 @@ export const getUsername = (api: Gitlab) => { export const cjsRequire = typeof require === 'undefined' ? createRequire(import.meta.url) : require -export const FALSY_VALUES = new Set(['false', '0']) - -export const TRUTHY_VALUES = new Set(['true', '1']) - export const GITLAB_MAX_TAGS = 4 export const HTTP_STATUS_NOT_FOUND = 404