deploy-vir 1.0.0 → 2.1.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/README.md CHANGED
@@ -26,13 +26,21 @@ export default defineDeployVirConfig({
26
26
  deploys: [
27
27
  {
28
28
  deployName: 'staging',
29
- fromBranch: 'dev',
30
- toBranch: 'staging',
29
+ branches: [
30
+ {
31
+ fromBranch: 'dev',
32
+ toBranch: 'staging',
33
+ },
34
+ ],
31
35
  },
32
36
  {
33
37
  deployName: 'prod',
34
- fromBranch: 'staging',
35
- toBranch: 'prod',
38
+ branches: [
39
+ {
40
+ fromBranch: 'staging',
41
+ toBranch: 'prod',
42
+ },
43
+ ],
36
44
  },
37
45
  ],
38
46
  },
package/dist/cli/cli.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { assertWrap } from '@augment-vir/assert';
2
- import { extractErrorMessage, log } from '@augment-vir/common';
2
+ import { awaitedForEach, extractErrorMessage, log } from '@augment-vir/common';
3
+ import { select } from '@inquirer/prompts';
3
4
  import { resolve } from 'node:path';
4
5
  import simpleGit from 'simple-git';
5
6
  import { getGitRemoteName, pushDeploy } from '../git.js';
@@ -12,9 +13,23 @@ import { sendNotifications } from '../notifications/send-notifications.js';
12
13
  */
13
14
  export async function runDeployVirCli({ args, y, }, cwd = process.cwd()) {
14
15
  const configPath = assertWrap.isTruthy(args[0], 'Missing config path.');
15
- const repoName = assertWrap.isTruthy(args[1], 'Missing repo name.');
16
- const deployName = assertWrap.isTruthy(args[2], 'Missing deploy name.');
17
16
  const config = (await import(resolve(cwd, configPath))).default;
17
+ const repoName = assertWrap.isTruthy(args[1] ||
18
+ (await select({
19
+ message: 'Choose a repo to deploy:',
20
+ choices: config.repos.map((repo) => {
21
+ return repo.name;
22
+ }),
23
+ })), 'Missing repo name.');
24
+ const deployName = assertWrap.isTruthy(args[2] ||
25
+ (await select({
26
+ message: 'Choose a deploy to trigger:',
27
+ choices: assertWrap
28
+ .isDefined(config.repos.find((repo) => repo.name === repoName), `Invalid repo name: '${repoName}'`)
29
+ .deploys.map((deploy) => {
30
+ return deploy.deployName;
31
+ }),
32
+ })), 'Missing deploy name.');
18
33
  await runDeployVir({
19
34
  cwd,
20
35
  deployName,
@@ -34,12 +49,15 @@ export async function runDeployVir(args, config) {
34
49
  const branchConfig = assertWrap.isDefined(repoConfig.deploys.find((deploy) => deploy.deployName === args.deployName, `Failed to find a deploy named '${args.deployName}' in repo '${args.repoName}'.`));
35
50
  const remoteName = await getGitRemoteName(git, repoConfig);
36
51
  log.faint(`Remote: ${remoteName}`);
37
- const deployResult = await pushDeploy(git, branchConfig, remoteName, args.bypassConfirmation);
38
- if (config.notifications?.length) {
39
- await sendNotifications(config.notifications, {
40
- branchConfig,
41
- deployResult,
42
- repoConfig,
52
+ const deployResults = await pushDeploy(git, branchConfig, remoteName, args.bypassConfirmation);
53
+ const notifications = config.notifications;
54
+ if (notifications?.length) {
55
+ await awaitedForEach(deployResults, async (deployResult) => {
56
+ await sendNotifications(notifications, {
57
+ branchConfig,
58
+ deployResult,
59
+ repoConfig,
60
+ });
43
61
  });
44
62
  }
45
63
  }
package/dist/config.d.ts CHANGED
@@ -90,8 +90,10 @@ export type DeployVirRepoConfig = {
90
90
  */
91
91
  export type DeployVirBranchConfig = {
92
92
  deployName: string;
93
- fromBranch: string;
94
- toBranch: string;
93
+ branches: {
94
+ fromBranch: string;
95
+ toBranch: string;
96
+ }[];
95
97
  };
96
98
  /**
97
99
  * Define a type safe deploy-vir config.
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, bypassConfirmation?: boolean): Promise<DeployResult>;
47
+ export declare function pushDeploy(git: Readonly<SimpleGit>, { deployName, branches }: Readonly<DeployVirBranchConfig>, remoteName: string, bypassConfirmation?: boolean): Promise<DeployResult[]>;
package/dist/git.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { assert, assertWrap, check } from '@augment-vir/assert';
2
- import { log, logColors } from '@augment-vir/common';
2
+ import { awaitedBlockingMap, log, logColors } from '@augment-vir/common';
3
3
  import { confirm } from '@inquirer/prompts';
4
4
  import { KnownError } from './known.error.js';
5
5
  /**
@@ -30,70 +30,72 @@ export async function getGitRemoteName(git, repoConfig) {
30
30
  *
31
31
  * @category Internal
32
32
  */
33
- export async function pushDeploy(git, { deployName, fromBranch, toBranch }, remoteName, bypassConfirmation = false) {
34
- assert.isTruthy(fromBranch, `Deploy '${deployName}' fromBranch cannot be empty.`);
35
- assert.isTruthy(toBranch, `Deploy '${deployName}' toBranch cannot be empty.`);
36
- assert.isTruthy(remoteName, 'Remote name cannot be empty.');
37
- log.faint(`Pushing ${remoteName}/${fromBranch} to ${toBranch}`);
38
- await git.fetch(remoteName, fromBranch);
39
- await git.fetch(remoteName, toBranch);
40
- const pushString = `${remoteName}/${fromBranch}:${toBranch}`;
41
- // Get the current commit on the target branch before pushing
42
- const beforeCommit = assertWrap.isDefined((await git.log([
43
- `${remoteName}/${toBranch}`,
44
- '-1',
45
- ])).latest, `Failed to get current commit for ${remoteName}/${toBranch}`);
46
- const afterCommit = assertWrap.isDefined((await git.log([
47
- `${remoteName}/${fromBranch}`,
48
- '-1',
49
- ])).latest, `Failed to get current commit for ${remoteName}/${fromBranch}`);
50
- /** Get commits that are on {@link toBranch} but not on {@link fromBranch}. */
51
- const commitsAhead = (await git.log([
52
- `${remoteName}/${toBranch}..${remoteName}/${fromBranch}`,
53
- ])).all;
54
- if (!commitsAhead.length) {
55
- throw new KnownError('No commit diff: nothing to deploy!');
56
- }
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) => {
33
+ export async function pushDeploy(git, { deployName, branches }, remoteName, bypassConfirmation = false) {
34
+ return await awaitedBlockingMap(branches, async ({ fromBranch, toBranch }) => {
35
+ assert.isTruthy(fromBranch, `Deploy '${deployName}' fromBranch cannot be empty.`);
36
+ assert.isTruthy(toBranch, `Deploy '${deployName}' toBranch cannot be empty.`);
37
+ assert.isTruthy(remoteName, 'Remote name cannot be empty.');
38
+ log.faint(`Pushing ${remoteName}/${fromBranch} to ${toBranch}`);
39
+ await git.fetch(remoteName, fromBranch);
40
+ await git.fetch(remoteName, toBranch);
41
+ const pushString = `${remoteName}/${fromBranch}:${toBranch}`;
42
+ // Get the current commit on the target branch before pushing
43
+ const beforeCommit = assertWrap.isDefined((await git.log([
44
+ `${remoteName}/${toBranch}`,
45
+ '-1',
46
+ ])).latest, `Failed to get current commit for ${remoteName}/${toBranch}`);
47
+ const afterCommit = assertWrap.isDefined((await git.log([
48
+ `${remoteName}/${fromBranch}`,
49
+ '-1',
50
+ ])).latest, `Failed to get current commit for ${remoteName}/${fromBranch}`);
51
+ /** Get commits that are on {@link toBranch} but not on {@link fromBranch}. */
52
+ const commitsAhead = (await git.log([
53
+ `${remoteName}/${toBranch}..${remoteName}/${fromBranch}`,
54
+ ])).all;
55
+ if (!commitsAhead.length) {
56
+ throw new KnownError('No commit diff: nothing to deploy!');
57
+ }
58
+ /** Get commits that are on {@link toBranch} but not on {@link fromBranch}. */
59
+ const commitsBehind = (await git.log([
60
+ `${remoteName}/${fromBranch}..${remoteName}/${toBranch}`,
61
+ ])).all;
62
+ const requiresForcePush = commitsBehind.length > 0;
63
+ log.info(`\n${requiresForcePush ? 'Only on' : 'Releasing from'} ${logColors.bold}${fromBranch}${logColors.reset}:`);
64
+ commitsAhead.forEach((commit, index) => {
69
65
  log.faint(` ${index + 1}. ${commit.hash.slice(0, 7)} (${commit.author_name}) - ${commit.message}`);
70
66
  });
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
- };
67
+ if (requiresForcePush) {
68
+ log.info(`\nOnly on ${logColors.bold}${toBranch}${logColors.reset}:`);
69
+ commitsBehind.forEach((commit, index) => {
70
+ log.faint(` ${index + 1}. ${commit.hash.slice(0, 7)} (${commit.author_name}) - ${commit.message}`);
71
+ });
72
+ }
73
+ const shouldPush = bypassConfirmation ||
74
+ (await confirm({
75
+ message: requiresForcePush
76
+ ? `\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}?`
77
+ : 'Ready to deploy?',
78
+ default: false,
79
+ }));
80
+ if (!shouldPush) {
81
+ throw new KnownError(`Deploy aborted.`);
82
+ }
83
+ if (requiresForcePush) {
84
+ await git.push(remoteName, pushString, ['--force']);
85
+ log.warning(`Force pushed ${logColors.bold}${fromBranch}${logColors.normalWeight} to ${logColors.bold}${toBranch}${logColors.reset}.`);
86
+ }
87
+ else {
88
+ await git.push(remoteName, pushString);
89
+ }
90
+ return {
91
+ deployCommits: {
92
+ deployedCommits: commitsAhead,
93
+ overwrittenCommits: commitsBehind,
94
+ },
95
+ branchStatus: {
96
+ before: beforeCommit,
97
+ after: afterCommit,
98
+ },
99
+ };
100
+ });
99
101
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deploy-vir",
3
- "version": "1.0.0",
3
+ "version": "2.1.0",
4
4
  "description": "Deploy a branch to another branch with notifications.",
5
5
  "keywords": [
6
6
  "deploy",
@@ -41,10 +41,10 @@
41
41
  "test:update": "npm run test update"
42
42
  },
43
43
  "dependencies": {
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",
44
+ "@augment-vir/assert": "^31.57.1",
45
+ "@augment-vir/common": "^31.57.1",
46
+ "@augment-vir/node": "^31.57.1",
47
+ "@inquirer/prompts": "^8.1.0",
48
48
  "@slack/web-api": "^7.13.0",
49
49
  "cli-vir": "^1.0.3",
50
50
  "simple-git": "^3.30.0",
@@ -53,15 +53,15 @@
53
53
  },
54
54
  "devDependencies": {
55
55
  "@eslint/eslintrc": "^3.3.3",
56
- "@eslint/js": "^9.39.1",
56
+ "@eslint/js": "^9.39.2",
57
57
  "@stylistic/eslint-plugin": "^5.6.1",
58
58
  "@stylistic/eslint-plugin-ts": "^4.4.1",
59
- "@types/node": "^24.3.0",
60
- "@typescript-eslint/eslint-plugin": "^8.47.0",
59
+ "@types/node": "^25.0.3",
60
+ "@typescript-eslint/eslint-plugin": "^8.50.1",
61
61
  "cspell": "^9.4.0",
62
- "dependency-cruiser": "^17.3.2",
63
- "esbuild": "^0.27.1",
64
- "eslint": "^9.39.1",
62
+ "dependency-cruiser": "^17.3.5",
63
+ "esbuild": "^0.27.2",
64
+ "eslint": "^9.39.2",
65
65
  "eslint-config-prettier": "^10.1.8",
66
66
  "eslint-plugin-jsdoc": "^61.5.0",
67
67
  "eslint-plugin-monorepo-cop": "^1.0.2",
@@ -72,11 +72,11 @@
72
72
  "eslint-plugin-unicorn": "^62.0.0",
73
73
  "istanbul-smart-text-reporter": "^1.1.5",
74
74
  "markdown-code-example-inserter": "^3.0.3",
75
- "npm-check-updates": "^19.1.2",
75
+ "npm-check-updates": "^19.2.0",
76
76
  "prettier": "~3.3.3",
77
77
  "prettier-plugin-interpolated-html-tags": "^2.0.1",
78
78
  "prettier-plugin-jsdoc": "^1.8.0",
79
- "prettier-plugin-multiline-arrays": "^4.0.5",
79
+ "prettier-plugin-multiline-arrays": "^4.1.3",
80
80
  "prettier-plugin-organize-imports": "^4.3.0",
81
81
  "prettier-plugin-packagejson": "^2.5.20",
82
82
  "prettier-plugin-sort-json": "^4.1.1",
@@ -84,8 +84,8 @@
84
84
  "runstorm": "^1.0.0",
85
85
  "typedoc": "^0.28.15",
86
86
  "typescript": "^5.9.3",
87
- "typescript-eslint": "^8.47.0",
88
- "virmator": "^14.3.3"
87
+ "typescript-eslint": "^8.50.1",
88
+ "virmator": "^14.4.0"
89
89
  },
90
90
  "engines": {
91
91
  "node": ">=22"
package/src/cli/cli.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import {assertWrap} from '@augment-vir/assert';
2
- import {extractErrorMessage, log} from '@augment-vir/common';
2
+ import {awaitedForEach, extractErrorMessage, log} from '@augment-vir/common';
3
+ import {select} from '@inquirer/prompts';
3
4
  import {resolve} from 'node:path';
4
5
  import simpleGit from 'simple-git';
5
6
  import {type DeployVirConfig} from '../config.js';
@@ -23,10 +24,34 @@ export async function runDeployVirCli(
23
24
  cwd = process.cwd(),
24
25
  ) {
25
26
  const configPath = assertWrap.isTruthy(args[0], 'Missing config path.');
26
- const repoName = assertWrap.isTruthy(args[1], 'Missing repo name.');
27
- const deployName = assertWrap.isTruthy(args[2], 'Missing deploy name.');
28
27
 
29
- const config = (await import(resolve(cwd, configPath))).default;
28
+ const config = (await import(resolve(cwd, configPath))).default as DeployVirConfig;
29
+
30
+ const repoName = assertWrap.isTruthy(
31
+ args[1] ||
32
+ (await select({
33
+ message: 'Choose a repo to deploy:',
34
+ choices: config.repos.map((repo) => {
35
+ return repo.name;
36
+ }),
37
+ })),
38
+ 'Missing repo name.',
39
+ );
40
+ const deployName = assertWrap.isTruthy(
41
+ args[2] ||
42
+ (await select({
43
+ message: 'Choose a deploy to trigger:',
44
+ choices: assertWrap
45
+ .isDefined(
46
+ config.repos.find((repo) => repo.name === repoName),
47
+ `Invalid repo name: '${repoName}'`,
48
+ )
49
+ .deploys.map((deploy) => {
50
+ return deploy.deployName;
51
+ }),
52
+ })),
53
+ 'Missing deploy name.',
54
+ );
30
55
 
31
56
  await runDeployVir(
32
57
  {
@@ -81,18 +106,22 @@ export async function runDeployVir(
81
106
  const remoteName = await getGitRemoteName(git, repoConfig);
82
107
  log.faint(`Remote: ${remoteName}`);
83
108
 
84
- const deployResult = await pushDeploy(
109
+ const deployResults = await pushDeploy(
85
110
  git,
86
111
  branchConfig,
87
112
  remoteName,
88
113
  args.bypassConfirmation,
89
114
  );
90
115
 
91
- if (config.notifications?.length) {
92
- await sendNotifications(config.notifications, {
93
- branchConfig,
94
- deployResult,
95
- repoConfig,
116
+ const notifications = config.notifications;
117
+
118
+ if (notifications?.length) {
119
+ await awaitedForEach(deployResults, async (deployResult) => {
120
+ await sendNotifications(notifications, {
121
+ branchConfig,
122
+ deployResult,
123
+ repoConfig,
124
+ });
96
125
  });
97
126
  }
98
127
  } catch (error) {
package/src/config.ts CHANGED
@@ -96,8 +96,10 @@ export type DeployVirRepoConfig = {
96
96
  */
97
97
  export type DeployVirBranchConfig = {
98
98
  deployName: string;
99
- fromBranch: string;
100
- toBranch: string;
99
+ branches: {
100
+ fromBranch: string;
101
+ toBranch: string;
102
+ }[];
101
103
  };
102
104
 
103
105
  /**
package/src/git.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import {assert, assertWrap, check} from '@augment-vir/assert';
2
- import {log, logColors} from '@augment-vir/common';
2
+ import {awaitedBlockingMap, log, logColors} from '@augment-vir/common';
3
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';
@@ -88,110 +88,112 @@ export type DeployResult = {
88
88
  */
89
89
  export async function pushDeploy(
90
90
  git: Readonly<SimpleGit>,
91
- {deployName, fromBranch, toBranch}: Readonly<DeployVirBranchConfig>,
91
+ {deployName, branches}: Readonly<DeployVirBranchConfig>,
92
92
  remoteName: string,
93
93
  bypassConfirmation = false,
94
- ): Promise<DeployResult> {
95
- assert.isTruthy(fromBranch, `Deploy '${deployName}' fromBranch cannot be empty.`);
96
- assert.isTruthy(toBranch, `Deploy '${deployName}' toBranch cannot be empty.`);
97
- assert.isTruthy(remoteName, 'Remote name cannot be empty.');
98
-
99
- log.faint(`Pushing ${remoteName}/${fromBranch} to ${toBranch}`);
100
-
101
- await git.fetch(remoteName, fromBranch);
102
- await git.fetch(remoteName, toBranch);
94
+ ): Promise<DeployResult[]> {
95
+ return await awaitedBlockingMap(branches, async ({fromBranch, toBranch}) => {
96
+ assert.isTruthy(fromBranch, `Deploy '${deployName}' fromBranch cannot be empty.`);
97
+ assert.isTruthy(toBranch, `Deploy '${deployName}' toBranch cannot be empty.`);
98
+ assert.isTruthy(remoteName, 'Remote name cannot be empty.');
99
+
100
+ log.faint(`Pushing ${remoteName}/${fromBranch} to ${toBranch}`);
101
+
102
+ await git.fetch(remoteName, fromBranch);
103
+ await git.fetch(remoteName, toBranch);
104
+
105
+ const pushString = `${remoteName}/${fromBranch}:${toBranch}`;
106
+
107
+ // Get the current commit on the target branch before pushing
108
+ const beforeCommit = assertWrap.isDefined(
109
+ (
110
+ await git.log([
111
+ `${remoteName}/${toBranch}`,
112
+ '-1',
113
+ ])
114
+ ).latest,
115
+ `Failed to get current commit for ${remoteName}/${toBranch}`,
116
+ );
103
117
 
104
- const pushString = `${remoteName}/${fromBranch}:${toBranch}`;
118
+ const afterCommit = assertWrap.isDefined(
119
+ (
120
+ await git.log([
121
+ `${remoteName}/${fromBranch}`,
122
+ '-1',
123
+ ])
124
+ ).latest,
125
+ `Failed to get current commit for ${remoteName}/${fromBranch}`,
126
+ );
105
127
 
106
- // Get the current commit on the target branch before pushing
107
- const beforeCommit = assertWrap.isDefined(
108
- (
128
+ /** Get commits that are on {@link toBranch} but not on {@link fromBranch}. */
129
+ const commitsAhead = (
109
130
  await git.log([
110
- `${remoteName}/${toBranch}`,
111
- '-1',
131
+ `${remoteName}/${toBranch}..${remoteName}/${fromBranch}`,
112
132
  ])
113
- ).latest,
114
- `Failed to get current commit for ${remoteName}/${toBranch}`,
115
- );
133
+ ).all;
134
+
135
+ if (!commitsAhead.length) {
136
+ throw new KnownError('No commit diff: nothing to deploy!');
137
+ }
116
138
 
117
- const afterCommit = assertWrap.isDefined(
118
- (
139
+ /** Get commits that are on {@link toBranch} but not on {@link fromBranch}. */
140
+ const commitsBehind = (
119
141
  await git.log([
120
- `${remoteName}/${fromBranch}`,
121
- '-1',
142
+ `${remoteName}/${fromBranch}..${remoteName}/${toBranch}`,
122
143
  ])
123
- ).latest,
124
- `Failed to get current commit for ${remoteName}/${fromBranch}`,
125
- );
126
-
127
- /** Get commits that are on {@link toBranch} but not on {@link fromBranch}. */
128
- const commitsAhead = (
129
- await git.log([
130
- `${remoteName}/${toBranch}..${remoteName}/${fromBranch}`,
131
- ])
132
- ).all;
133
-
134
- if (!commitsAhead.length) {
135
- throw new KnownError('No commit diff: nothing to deploy!');
136
- }
137
-
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;
144
+ ).all;
144
145
 
145
- const requiresForcePush = commitsBehind.length > 0;
146
+ const requiresForcePush = commitsBehind.length > 0;
146
147
 
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}`,
148
+ log.info(
149
+ `\n${requiresForcePush ? 'Only on' : 'Releasing from'} ${logColors.bold}${fromBranch}${logColors.reset}:`,
153
150
  );
154
- });
155
-
156
- if (requiresForcePush) {
157
- log.info(`\nOnly on ${logColors.bold}${toBranch}${logColors.reset}:`);
158
- commitsBehind.forEach((commit, index) => {
151
+ commitsAhead.forEach((commit, index) => {
159
152
  log.faint(
160
153
  ` ${index + 1}. ${commit.hash.slice(0, 7)} (${commit.author_name}) - ${commit.message}`,
161
154
  );
162
155
  });
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
156
 
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);
185
- }
186
-
187
- return {
188
- deployCommits: {
189
- deployedCommits: commitsAhead,
190
- overwrittenCommits: commitsBehind,
191
- },
192
- branchStatus: {
193
- before: beforeCommit,
194
- after: afterCommit,
195
- },
196
- };
157
+ if (requiresForcePush) {
158
+ log.info(`\nOnly on ${logColors.bold}${toBranch}${logColors.reset}:`);
159
+ commitsBehind.forEach((commit, index) => {
160
+ log.faint(
161
+ ` ${index + 1}. ${commit.hash.slice(0, 7)} (${commit.author_name}) - ${commit.message}`,
162
+ );
163
+ });
164
+ }
165
+
166
+ const shouldPush =
167
+ bypassConfirmation ||
168
+ (await confirm({
169
+ message: requiresForcePush
170
+ ? `\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}?`
171
+ : 'Ready to deploy?',
172
+ default: false,
173
+ }));
174
+
175
+ if (!shouldPush) {
176
+ throw new KnownError(`Deploy aborted.`);
177
+ }
178
+
179
+ if (requiresForcePush) {
180
+ await git.push(remoteName, pushString, ['--force']);
181
+ log.warning(
182
+ `Force pushed ${logColors.bold}${fromBranch}${logColors.normalWeight} to ${logColors.bold}${toBranch}${logColors.reset}.`,
183
+ );
184
+ } else {
185
+ await git.push(remoteName, pushString);
186
+ }
187
+
188
+ return {
189
+ deployCommits: {
190
+ deployedCommits: commitsAhead,
191
+ overwrittenCommits: commitsBehind,
192
+ },
193
+ branchStatus: {
194
+ before: beforeCommit,
195
+ after: afterCommit,
196
+ },
197
+ };
198
+ });
197
199
  }