deploy-vir 0.2.9 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/cli.d.ts CHANGED
@@ -4,7 +4,10 @@ import { type DeployVirConfig } from '../config.js';
4
4
  *
5
5
  * @category Internal
6
6
  */
7
- export declare function runDeployVirCli(args: ReadonlyArray<string>, cwd?: string): Promise<void>;
7
+ export declare function runDeployVirCli({ args, y, }: {
8
+ y: boolean;
9
+ args: ReadonlyArray<string>;
10
+ }, cwd?: string): Promise<void>;
8
11
  /**
9
12
  * Args for {@link runDeployVir}.
10
13
  *
@@ -16,6 +19,8 @@ export type DeployVirArgs = {
16
19
  /** This much match a deploy name in your config. */
17
20
  deployName: string;
18
21
  cwd: string;
22
+ /** If true, manual confirmation is not required. */
23
+ bypassConfirmation: boolean;
19
24
  };
20
25
  /**
21
26
  * Run a deploy.
package/dist/cli/cli.js CHANGED
@@ -10,12 +10,17 @@ import { sendNotifications } from '../notifications/send-notifications.js';
10
10
  *
11
11
  * @category Internal
12
12
  */
13
- export async function runDeployVirCli(args, cwd = process.cwd()) {
13
+ export async function runDeployVirCli({ args, y, }, cwd = process.cwd()) {
14
14
  const configPath = assertWrap.isTruthy(args[0], 'Missing config path.');
15
15
  const repoName = assertWrap.isTruthy(args[1], 'Missing repo name.');
16
16
  const deployName = assertWrap.isTruthy(args[2], 'Missing deploy name.');
17
17
  const config = (await import(resolve(cwd, configPath))).default;
18
- await runDeployVir({ cwd, deployName, repoName }, config);
18
+ await runDeployVir({
19
+ cwd,
20
+ deployName,
21
+ repoName,
22
+ bypassConfirmation: y,
23
+ }, config);
19
24
  }
20
25
  /**
21
26
  * Run a deploy.
@@ -29,7 +34,7 @@ export async function runDeployVir(args, config) {
29
34
  const branchConfig = assertWrap.isDefined(repoConfig.deploys.find((deploy) => deploy.deployName === args.deployName, `Failed to find a deploy named '${args.deployName}' in repo '${args.repoName}'.`));
30
35
  const remoteName = await getGitRemoteName(git, repoConfig);
31
36
  log.faint(`Remote: ${remoteName}`);
32
- const deployResult = await pushDeploy(git, branchConfig, remoteName);
37
+ const deployResult = await pushDeploy(git, branchConfig, remoteName, args.bypassConfirmation);
33
38
  if (config.notifications?.length) {
34
39
  await sendNotifications(config.notifications, {
35
40
  branchConfig,
@@ -1,7 +1,18 @@
1
- import { extractRelevantArgs } from '@augment-vir/node';
1
+ import { FlagRequirement, parseArgs } from 'cli-vir';
2
2
  import { runDeployVirCli } from './cli.js';
3
- await runDeployVirCli(extractRelevantArgs({
3
+ await runDeployVirCli(parseArgs(process.argv, {
4
+ y: {
5
+ flag: {
6
+ valueRequirement: FlagRequirement.Blocked,
7
+ },
8
+ description: 'If set, bypass manual validation.',
9
+ },
10
+ args: {
11
+ position: {
12
+ rest: true,
13
+ },
14
+ },
15
+ }, {
4
16
  binName: 'deploy-vir',
5
- fileName: import.meta.filename,
6
- rawArgs: process.argv,
17
+ importMeta: import.meta,
7
18
  }), process.cwd());
package/dist/git.d.ts CHANGED
@@ -44,4 +44,4 @@ export type DeployResult = {
44
44
  *
45
45
  * @category Internal
46
46
  */
47
- export declare function pushDeploy(git: Readonly<SimpleGit>, { deployName, fromBranch, toBranch }: Readonly<DeployVirBranchConfig>, remoteName: string): Promise<DeployResult>;
47
+ export declare function pushDeploy(git: Readonly<SimpleGit>, { deployName, fromBranch, toBranch }: Readonly<DeployVirBranchConfig>, remoteName: string, bypassConfirmation?: boolean): Promise<DeployResult>;
package/dist/git.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { assert, assertWrap, check } from '@augment-vir/assert';
2
- import { extractErrorMessage, log, logColors } from '@augment-vir/common';
3
- import { askQuestion } from '@augment-vir/node';
2
+ import { log, logColors } from '@augment-vir/common';
3
+ import { confirm } from '@inquirer/prompts';
4
4
  import { KnownError } from './known.error.js';
5
5
  /**
6
6
  * Find the git remote's name, or create a new one.
@@ -30,7 +30,7 @@ export async function getGitRemoteName(git, repoConfig) {
30
30
  *
31
31
  * @category Internal
32
32
  */
33
- export async function pushDeploy(git, { deployName, fromBranch, toBranch }, remoteName) {
33
+ export async function pushDeploy(git, { deployName, fromBranch, toBranch }, remoteName, bypassConfirmation = false) {
34
34
  assert.isTruthy(fromBranch, `Deploy '${deployName}' fromBranch cannot be empty.`);
35
35
  assert.isTruthy(toBranch, `Deploy '${deployName}' toBranch cannot be empty.`);
36
36
  assert.isTruthy(remoteName, 'Remote name cannot be empty.');
@@ -54,56 +54,46 @@ export async function pushDeploy(git, { deployName, fromBranch, toBranch }, remo
54
54
  if (!commitsAhead.length) {
55
55
  throw new KnownError('No commit diff: nothing to deploy!');
56
56
  }
57
- try {
58
- await git.push(remoteName, pushString);
59
- return {
60
- deployCommits: {
61
- deployedCommits: commitsAhead,
62
- overwrittenCommits: [],
63
- },
64
- branchStatus: {
65
- before: beforeCommit,
66
- after: afterCommit,
67
- },
68
- };
69
- }
70
- catch (error) {
71
- log.error(`Push failed: ${extractErrorMessage(error)}`);
72
- /** Get commits that are on {@link toBranch} but not on {@link fromBranch}. */
73
- const commitsBehind = (await git.log([
74
- `${remoteName}/${fromBranch}..${remoteName}/${toBranch}`,
75
- ])).all;
76
- if (commitsBehind.length > 0) {
77
- log.info(`\nOnly on ${logColors.bold}${fromBranch}${logColors.reset}:`);
78
- commitsAhead.forEach((commit, index) => {
79
- log.faint(` ${index + 1}. ${commit.hash.slice(0, 7)} (${commit.author_name}) - ${commit.message}`);
80
- });
81
- log.info(`\nOnly on ${logColors.bold}${toBranch}${logColors.reset}:`);
82
- commitsBehind.forEach((commit, index) => {
83
- log.faint(` ${index + 1}. ${commit.hash.slice(0, 7)} (${commit.author_name}) - ${commit.message}`);
84
- });
85
- }
86
- const shouldForcePush = await askQuestion(`\nDo you want to force push ${logColors.bold}${fromBranch}${logColors.reset} to ${logColors.bold}${toBranch}${logColors.reset}?\n\n${logColors.warning}This will overwrite the commits only on ${logColors.bold}${toBranch}${logColors.normalWeight}.${logColors.reset} (y/N): `, {
87
- timeout: {
88
- hours: 2,
89
- },
57
+ /** Get commits that are on {@link toBranch} but not on {@link fromBranch}. */
58
+ const commitsBehind = (await git.log([
59
+ `${remoteName}/${fromBranch}..${remoteName}/${toBranch}`,
60
+ ])).all;
61
+ const requiresForcePush = commitsBehind.length > 0;
62
+ log.info(`\n${requiresForcePush ? 'Only on' : 'Releasing from'} ${logColors.bold}${fromBranch}${logColors.reset}:`);
63
+ commitsAhead.forEach((commit, index) => {
64
+ log.faint(` ${index + 1}. ${commit.hash.slice(0, 7)} (${commit.author_name}) - ${commit.message}`);
65
+ });
66
+ if (requiresForcePush) {
67
+ log.info(`\nOnly on ${logColors.bold}${toBranch}${logColors.reset}:`);
68
+ commitsBehind.forEach((commit, index) => {
69
+ log.faint(` ${index + 1}. ${commit.hash.slice(0, 7)} (${commit.author_name}) - ${commit.message}`);
90
70
  });
91
- if (shouldForcePush.toLowerCase() === 'y' || shouldForcePush.toLowerCase() === 'yes') {
92
- await git.push(remoteName, pushString, ['--force']);
93
- log.warning(`Force pushed ${logColors.bold}${fromBranch}${logColors.reset} to ${logColors.bold}${toBranch}${logColors.reset}.`);
94
- }
95
- else {
96
- throw new KnownError(`Deploy aborted.`);
97
- }
98
- return {
99
- deployCommits: {
100
- deployedCommits: commitsAhead,
101
- overwrittenCommits: commitsBehind,
102
- },
103
- branchStatus: {
104
- before: beforeCommit,
105
- after: afterCommit,
106
- },
107
- };
108
71
  }
72
+ const shouldPush = bypassConfirmation ||
73
+ (await confirm({
74
+ message: requiresForcePush
75
+ ? `\n${logColors.warning}Do you want to force push ${logColors.bold}${fromBranch}${logColors.normalWeight} to ${logColors.bold}${toBranch}${logColors.normalWeight}?\n\nThis will overwrite the commits only on ${logColors.bold}${toBranch}${logColors.normalWeight}.${logColors.reset}?`
76
+ : 'Ready to deploy?',
77
+ default: false,
78
+ }));
79
+ if (!shouldPush) {
80
+ throw new KnownError(`Deploy aborted.`);
81
+ }
82
+ if (requiresForcePush) {
83
+ await git.push(remoteName, pushString, ['--force']);
84
+ log.warning(`Force pushed ${logColors.bold}${fromBranch}${logColors.normalWeight} to ${logColors.bold}${toBranch}${logColors.reset}.`);
85
+ }
86
+ else {
87
+ await git.push(remoteName, pushString);
88
+ }
89
+ return {
90
+ deployCommits: {
91
+ deployedCommits: commitsAhead,
92
+ overwrittenCommits: commitsBehind,
93
+ },
94
+ branchStatus: {
95
+ before: beforeCommit,
96
+ after: afterCommit,
97
+ },
98
+ };
109
99
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deploy-vir",
3
- "version": "0.2.9",
3
+ "version": "1.0.0",
4
4
  "description": "Deploy a branch to another branch with notifications.",
5
5
  "keywords": [
6
6
  "deploy",
@@ -32,7 +32,7 @@
32
32
  "format": "virmator format",
33
33
  "lint": "virmator lint fix",
34
34
  "publish": "virmator publish npm run test:all",
35
- "test:all": "npm run compile && concurrently --colors --kill-others-on-fail -c auto --names spelling,format,docs,deps,lint \"npm run test:spelling\" \"npm run test:format\" \"npm run test:docs\" \"npm run test:deps\" \"npm run test:lint\"",
35
+ "test:all": "npm run compile && runstorm --names spelling,format,docs,deps,lint \"npm run test:spelling\" \"npm run test:format\" \"npm run test:docs\" \"npm run test:deps\" \"npm run test:lint\"",
36
36
  "test:deps": "virmator deps check",
37
37
  "test:docs": "virmator docs check",
38
38
  "test:format": "virmator format check",
@@ -41,48 +41,51 @@
41
41
  "test:update": "npm run test update"
42
42
  },
43
43
  "dependencies": {
44
- "@augment-vir/assert": "^31.32.2",
45
- "@augment-vir/common": "^31.32.2",
46
- "@augment-vir/node": "^31.32.2",
47
- "@slack/web-api": "^7.9.3",
48
- "simple-git": "^3.28.0",
49
- "tsx": "^4.20.4",
50
- "url-vir": "^2.1.3"
44
+ "@augment-vir/assert": "^31.54.3",
45
+ "@augment-vir/common": "^31.54.3",
46
+ "@augment-vir/node": "^31.54.3",
47
+ "@inquirer/prompts": "^8.0.2",
48
+ "@slack/web-api": "^7.13.0",
49
+ "cli-vir": "^1.0.3",
50
+ "simple-git": "^3.30.0",
51
+ "tsx": "^4.21.0",
52
+ "url-vir": "^2.1.7"
51
53
  },
52
54
  "devDependencies": {
53
- "@eslint/eslintrc": "^3.3.1",
54
- "@eslint/js": "^9.33.0",
55
- "@stylistic/eslint-plugin": "^5.2.3",
55
+ "@eslint/eslintrc": "^3.3.3",
56
+ "@eslint/js": "^9.39.1",
57
+ "@stylistic/eslint-plugin": "^5.6.1",
56
58
  "@stylistic/eslint-plugin-ts": "^4.4.1",
57
- "@types/node": "^24.2.1",
58
- "@typescript-eslint/eslint-plugin": "^8.39.1",
59
- "cspell": "^9.2.0",
60
- "dependency-cruiser": "^17.0.1",
61
- "esbuild": "^0.25.9",
62
- "eslint": "^9.33.0",
59
+ "@types/node": "^24.3.0",
60
+ "@typescript-eslint/eslint-plugin": "^8.47.0",
61
+ "cspell": "^9.4.0",
62
+ "dependency-cruiser": "^17.3.2",
63
+ "esbuild": "^0.27.1",
64
+ "eslint": "^9.39.1",
63
65
  "eslint-config-prettier": "^10.1.8",
64
- "eslint-plugin-jsdoc": "^54.0.0",
66
+ "eslint-plugin-jsdoc": "^61.5.0",
65
67
  "eslint-plugin-monorepo-cop": "^1.0.2",
66
- "eslint-plugin-playwright": "^2.2.2",
68
+ "eslint-plugin-playwright": "^2.4.0",
67
69
  "eslint-plugin-prettier": "^5.5.4",
68
70
  "eslint-plugin-require-extensions": "^0.1.3",
69
- "eslint-plugin-sonarjs": "^3.0.4",
70
- "eslint-plugin-unicorn": "^57.0.0",
71
+ "eslint-plugin-sonarjs": "^3.0.5",
72
+ "eslint-plugin-unicorn": "^62.0.0",
71
73
  "istanbul-smart-text-reporter": "^1.1.5",
72
74
  "markdown-code-example-inserter": "^3.0.3",
73
- "npm-check-updates": "^18.0.2",
75
+ "npm-check-updates": "^19.1.2",
74
76
  "prettier": "~3.3.3",
75
77
  "prettier-plugin-interpolated-html-tags": "^2.0.1",
76
- "prettier-plugin-jsdoc": "^1.3.3",
77
- "prettier-plugin-multiline-arrays": "^4.0.3",
78
- "prettier-plugin-organize-imports": "^4.2.0",
79
- "prettier-plugin-packagejson": "^2.5.19",
78
+ "prettier-plugin-jsdoc": "^1.8.0",
79
+ "prettier-plugin-multiline-arrays": "^4.0.5",
80
+ "prettier-plugin-organize-imports": "^4.3.0",
81
+ "prettier-plugin-packagejson": "^2.5.20",
80
82
  "prettier-plugin-sort-json": "^4.1.1",
81
83
  "prettier-plugin-toml": "^2.0.6",
82
- "typedoc": "^0.28.10",
83
- "typescript": "^5.9.2",
84
- "typescript-eslint": "^8.39.1",
85
- "virmator": "^13.16.2"
84
+ "runstorm": "^1.0.0",
85
+ "typedoc": "^0.28.15",
86
+ "typescript": "^5.9.3",
87
+ "typescript-eslint": "^8.47.0",
88
+ "virmator": "^14.3.3"
86
89
  },
87
90
  "engines": {
88
91
  "node": ">=22"
@@ -1,11 +1,26 @@
1
- import {extractRelevantArgs} from '@augment-vir/node';
1
+ import {FlagRequirement, parseArgs} from 'cli-vir';
2
2
  import {runDeployVirCli} from './cli.js';
3
3
 
4
4
  await runDeployVirCli(
5
- extractRelevantArgs({
6
- binName: 'deploy-vir',
7
- fileName: import.meta.filename,
8
- rawArgs: process.argv,
9
- }),
5
+ parseArgs(
6
+ process.argv,
7
+ {
8
+ y: {
9
+ flag: {
10
+ valueRequirement: FlagRequirement.Blocked,
11
+ },
12
+ description: 'If set, bypass manual validation.',
13
+ },
14
+ args: {
15
+ position: {
16
+ rest: true,
17
+ },
18
+ },
19
+ },
20
+ {
21
+ binName: 'deploy-vir',
22
+ importMeta: import.meta,
23
+ },
24
+ ),
10
25
  process.cwd(),
11
26
  );
package/src/cli/cli.ts CHANGED
@@ -12,14 +12,31 @@ import {sendNotifications} from '../notifications/send-notifications.js';
12
12
  *
13
13
  * @category Internal
14
14
  */
15
- export async function runDeployVirCli(args: ReadonlyArray<string>, cwd = process.cwd()) {
15
+ export async function runDeployVirCli(
16
+ {
17
+ args,
18
+ y,
19
+ }: {
20
+ y: boolean;
21
+ args: ReadonlyArray<string>;
22
+ },
23
+ cwd = process.cwd(),
24
+ ) {
16
25
  const configPath = assertWrap.isTruthy(args[0], 'Missing config path.');
17
26
  const repoName = assertWrap.isTruthy(args[1], 'Missing repo name.');
18
27
  const deployName = assertWrap.isTruthy(args[2], 'Missing deploy name.');
19
28
 
20
29
  const config = (await import(resolve(cwd, configPath))).default;
21
30
 
22
- await runDeployVir({cwd, deployName, repoName}, config);
31
+ await runDeployVir(
32
+ {
33
+ cwd,
34
+ deployName,
35
+ repoName,
36
+ bypassConfirmation: y,
37
+ },
38
+ config,
39
+ );
23
40
  }
24
41
 
25
42
  /**
@@ -33,6 +50,8 @@ export type DeployVirArgs = {
33
50
  /** This much match a deploy name in your config. */
34
51
  deployName: string;
35
52
  cwd: string;
53
+ /** If true, manual confirmation is not required. */
54
+ bypassConfirmation: boolean;
36
55
  };
37
56
 
38
57
  /**
@@ -62,7 +81,12 @@ export async function runDeployVir(
62
81
  const remoteName = await getGitRemoteName(git, repoConfig);
63
82
  log.faint(`Remote: ${remoteName}`);
64
83
 
65
- const deployResult = await pushDeploy(git, branchConfig, remoteName);
84
+ const deployResult = await pushDeploy(
85
+ git,
86
+ branchConfig,
87
+ remoteName,
88
+ args.bypassConfirmation,
89
+ );
66
90
 
67
91
  if (config.notifications?.length) {
68
92
  await sendNotifications(config.notifications, {
package/src/git.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import {assert, assertWrap, check} from '@augment-vir/assert';
2
- import {extractErrorMessage, log, logColors} from '@augment-vir/common';
3
- import {askQuestion} from '@augment-vir/node';
2
+ import {log, logColors} from '@augment-vir/common';
3
+ import {confirm} from '@inquirer/prompts';
4
4
  import {type DefaultLogFields, type ListLogLine, type SimpleGit} from 'simple-git';
5
5
  import {type DeployVirBranchConfig, type DeployVirRepoConfig} from './config.js';
6
6
  import {KnownError} from './known.error.js';
@@ -90,6 +90,7 @@ export async function pushDeploy(
90
90
  git: Readonly<SimpleGit>,
91
91
  {deployName, fromBranch, toBranch}: Readonly<DeployVirBranchConfig>,
92
92
  remoteName: string,
93
+ bypassConfirmation = false,
93
94
  ): Promise<DeployResult> {
94
95
  assert.isTruthy(fromBranch, `Deploy '${deployName}' fromBranch cannot be empty.`);
95
96
  assert.isTruthy(toBranch, `Deploy '${deployName}' toBranch cannot be empty.`);
@@ -134,72 +135,63 @@ export async function pushDeploy(
134
135
  throw new KnownError('No commit diff: nothing to deploy!');
135
136
  }
136
137
 
137
- try {
138
- await git.push(remoteName, pushString);
138
+ /** Get commits that are on {@link toBranch} but not on {@link fromBranch}. */
139
+ const commitsBehind = (
140
+ await git.log([
141
+ `${remoteName}/${fromBranch}..${remoteName}/${toBranch}`,
142
+ ])
143
+ ).all;
139
144
 
140
- return {
141
- deployCommits: {
142
- deployedCommits: commitsAhead,
143
- overwrittenCommits: [],
144
- },
145
- branchStatus: {
146
- before: beforeCommit,
147
- after: afterCommit,
148
- },
149
- };
150
- } catch (error) {
151
- log.error(`Push failed: ${extractErrorMessage(error)}`);
152
-
153
- /** Get commits that are on {@link toBranch} but not on {@link fromBranch}. */
154
- const commitsBehind = (
155
- await git.log([
156
- `${remoteName}/${fromBranch}..${remoteName}/${toBranch}`,
157
- ])
158
- ).all;
159
-
160
- if (commitsBehind.length > 0) {
161
- log.info(`\nOnly on ${logColors.bold}${fromBranch}${logColors.reset}:`);
162
- commitsAhead.forEach((commit, index) => {
163
- log.faint(
164
- ` ${index + 1}. ${commit.hash.slice(0, 7)} (${commit.author_name}) - ${commit.message}`,
165
- );
166
- });
167
-
168
- log.info(`\nOnly on ${logColors.bold}${toBranch}${logColors.reset}:`);
169
- commitsBehind.forEach((commit, index) => {
170
- log.faint(
171
- ` ${index + 1}. ${commit.hash.slice(0, 7)} (${commit.author_name}) - ${commit.message}`,
172
- );
173
- });
174
- }
175
-
176
- const shouldForcePush = await askQuestion(
177
- `\nDo you want to force push ${logColors.bold}${fromBranch}${logColors.reset} to ${logColors.bold}${toBranch}${logColors.reset}?\n\n${logColors.warning}This will overwrite the commits only on ${logColors.bold}${toBranch}${logColors.normalWeight}.${logColors.reset} (y/N): `,
178
- {
179
- timeout: {
180
- hours: 2,
181
- },
182
- },
145
+ const requiresForcePush = commitsBehind.length > 0;
146
+
147
+ log.info(
148
+ `\n${requiresForcePush ? 'Only on' : 'Releasing from'} ${logColors.bold}${fromBranch}${logColors.reset}:`,
149
+ );
150
+ commitsAhead.forEach((commit, index) => {
151
+ log.faint(
152
+ ` ${index + 1}. ${commit.hash.slice(0, 7)} (${commit.author_name}) - ${commit.message}`,
183
153
  );
154
+ });
184
155
 
185
- if (shouldForcePush.toLowerCase() === 'y' || shouldForcePush.toLowerCase() === 'yes') {
186
- await git.push(remoteName, pushString, ['--force']);
187
- log.warning(
188
- `Force pushed ${logColors.bold}${fromBranch}${logColors.reset} to ${logColors.bold}${toBranch}${logColors.reset}.`,
156
+ if (requiresForcePush) {
157
+ log.info(`\nOnly on ${logColors.bold}${toBranch}${logColors.reset}:`);
158
+ commitsBehind.forEach((commit, index) => {
159
+ log.faint(
160
+ ` ${index + 1}. ${commit.hash.slice(0, 7)} (${commit.author_name}) - ${commit.message}`,
189
161
  );
190
- } else {
191
- throw new KnownError(`Deploy aborted.`);
192
- }
193
-
194
- return {
195
- deployCommits: {
196
- deployedCommits: commitsAhead,
197
- overwrittenCommits: commitsBehind,
198
- },
199
- branchStatus: {
200
- before: beforeCommit,
201
- after: afterCommit,
202
- },
203
- };
162
+ });
163
+ }
164
+
165
+ const shouldPush =
166
+ bypassConfirmation ||
167
+ (await confirm({
168
+ message: requiresForcePush
169
+ ? `\n${logColors.warning}Do you want to force push ${logColors.bold}${fromBranch}${logColors.normalWeight} to ${logColors.bold}${toBranch}${logColors.normalWeight}?\n\nThis will overwrite the commits only on ${logColors.bold}${toBranch}${logColors.normalWeight}.${logColors.reset}?`
170
+ : 'Ready to deploy?',
171
+ default: false,
172
+ }));
173
+
174
+ if (!shouldPush) {
175
+ throw new KnownError(`Deploy aborted.`);
176
+ }
177
+
178
+ if (requiresForcePush) {
179
+ await git.push(remoteName, pushString, ['--force']);
180
+ log.warning(
181
+ `Force pushed ${logColors.bold}${fromBranch}${logColors.normalWeight} to ${logColors.bold}${toBranch}${logColors.reset}.`,
182
+ );
183
+ } else {
184
+ await git.push(remoteName, pushString);
204
185
  }
186
+
187
+ return {
188
+ deployCommits: {
189
+ deployedCommits: commitsAhead,
190
+ overwrittenCommits: commitsBehind,
191
+ },
192
+ branchStatus: {
193
+ before: beforeCommit,
194
+ after: afterCommit,
195
+ },
196
+ };
205
197
  }