@apexdevtools/git-ops 1.1.0 → 1.2.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/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # git-ops - Changelog
2
2
 
3
+ ## 1.2.0 - 2023-09-15
4
+
5
+ - Add `OrgTracking` class
6
+ - adds the ability to get local status against the default org
7
+ - adds the ability to deploy and update source tracking given file paths
8
+ - remove patch version checking in Git version
9
+
10
+ ## 1.1.1 - 2023-03-27
11
+
12
+ - Update minimum version to 2.20.0
13
+
3
14
  ## 1.1.0 - 2023-03-21
4
15
 
5
16
  - add new method `getDiffRange`
package/README.md CHANGED
@@ -4,7 +4,7 @@ Library to do git operations to find changed files in a given git repository.
4
4
 
5
5
  ## Prerequisite
6
6
 
7
- Minimum `git` version of `2.30.0` must already be installed on the host machine.
7
+ Minimum `git` version of `2.20.0` must already be installed on the host machine.
8
8
 
9
9
  ## Getting Started
10
10
 
@@ -15,7 +15,6 @@ export declare enum FileStatus {
15
15
  export declare class Git implements IGit {
16
16
  private static MIN_GIT_VERSION_MAJOR;
17
17
  private static MIN_GIT_VERSION_MINOR;
18
- private static MIN_GIT_VERSION_PATCH;
19
18
  private gitInstance;
20
19
  private dir;
21
20
  constructor(dir: string);
@@ -36,10 +36,12 @@ class Git {
36
36
  return __awaiter(this, void 0, void 0, function* () {
37
37
  const version = yield git.version();
38
38
  const isSupported = version.major >= this.MIN_GIT_VERSION_MAJOR &&
39
- version.minor >= this.MIN_GIT_VERSION_MINOR &&
40
- version.patch >= this.MIN_GIT_VERSION_PATCH;
39
+ version.minor >= this.MIN_GIT_VERSION_MINOR;
40
+ if (!version.installed) {
41
+ throw new Error('"git" is not installed or available on the PATH');
42
+ }
41
43
  if (!isSupported)
42
- throw new Error(`Unsupported version of git. Min version must be ${this.MIN_GIT_VERSION_MAJOR}.${this.MIN_GIT_VERSION_MINOR}.${this.MIN_GIT_VERSION_PATCH}`);
44
+ throw new Error(`Unsupported version of git. Min version must be ${this.MIN_GIT_VERSION_MAJOR}.${this.MIN_GIT_VERSION_MINOR}`);
43
45
  });
44
46
  }
45
47
  get git() {
@@ -105,5 +107,4 @@ class Git {
105
107
  }
106
108
  exports.Git = Git;
107
109
  Git.MIN_GIT_VERSION_MAJOR = 2;
108
- Git.MIN_GIT_VERSION_MINOR = 30;
109
- Git.MIN_GIT_VERSION_PATCH = 0;
110
+ Git.MIN_GIT_VERSION_MINOR = 20;
@@ -0,0 +1,37 @@
1
+ import { Connection } from '@salesforce/core';
2
+ import { Logger } from '../logger/Logger';
3
+ export declare enum FileState {
4
+ Added = "add",
5
+ Modified = "modify",
6
+ Deleted = "delete",
7
+ NonDelete = "nondelete",
8
+ Ignored = "ignore",
9
+ Conflicted = "conflict"
10
+ }
11
+ export interface SyncStatusRow {
12
+ fullName: string;
13
+ path?: string;
14
+ state: FileState[];
15
+ type: string;
16
+ origin: string;
17
+ }
18
+ export interface SyncStatus {
19
+ local: SyncStatusRow[];
20
+ remote: SyncStatusRow[];
21
+ }
22
+ export interface OrgTrackingOptions {
23
+ connection: Connection;
24
+ projectDir: string;
25
+ logger: Logger;
26
+ }
27
+ export declare class OrgTracking {
28
+ private options;
29
+ private logger;
30
+ constructor(options: OrgTrackingOptions);
31
+ getLocalStatus(withConflicts?: boolean): Promise<SyncStatus>;
32
+ deployAndUpdateSourceTracking(paths: Array<string>): Promise<void>;
33
+ private deploy;
34
+ private updateSourceTracking;
35
+ private toSyncStatusRow;
36
+ private withWorkingDir;
37
+ }
@@ -0,0 +1,139 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright (c) 2023 Certinia Inc. All rights reserved.
4
+ */
5
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
6
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
7
+ return new (P || (P = Promise))(function (resolve, reject) {
8
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
9
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
10
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
11
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
12
+ });
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.OrgTracking = exports.FileState = void 0;
16
+ const core_1 = require("@salesforce/core");
17
+ const process_1 = require("process");
18
+ const source_tracking_1 = require("@salesforce/source-tracking");
19
+ const source_deploy_retrieve_1 = require("@salesforce/source-deploy-retrieve");
20
+ var FileState;
21
+ (function (FileState) {
22
+ FileState["Added"] = "add";
23
+ FileState["Modified"] = "modify";
24
+ FileState["Deleted"] = "delete";
25
+ FileState["NonDelete"] = "nondelete";
26
+ FileState["Ignored"] = "ignore";
27
+ FileState["Conflicted"] = "conflict";
28
+ })(FileState = exports.FileState || (exports.FileState = {}));
29
+ class OrgTracking {
30
+ constructor(options) {
31
+ this.options = options;
32
+ this.logger = options.logger;
33
+ }
34
+ getLocalStatus(withConflicts = false) {
35
+ return __awaiter(this, void 0, void 0, function* () {
36
+ const project = core_1.SfProject.getInstance(this.options.projectDir);
37
+ const org = yield core_1.Org.create({ connection: this.options.connection });
38
+ return yield this.withWorkingDir(this.options.projectDir, () => __awaiter(this, void 0, void 0, function* () {
39
+ const tracking = yield source_tracking_1.SourceTracking.create({
40
+ org,
41
+ project,
42
+ ignoreLocalCache: true,
43
+ });
44
+ yield tracking.ensureRemoteTracking(true);
45
+ const initValue = { local: [], remote: [] };
46
+ const status = yield tracking
47
+ .getStatus({ local: true, remote: false })
48
+ .then((res) => __awaiter(this, void 0, void 0, function* () {
49
+ if (withConflicts) {
50
+ //Taken from sourceTracking.ts from the @salesforce/source-tracking lib
51
+ const conflictFiles = (yield tracking.getConflicts())
52
+ .flatMap(conflict => conflict.filenames)
53
+ .filter((value) => typeof value === 'string');
54
+ res = res.map(row => (Object.assign(Object.assign({}, row), { conflict: !!row.filePath && conflictFiles.includes(row.filePath) })));
55
+ }
56
+ return res;
57
+ }))
58
+ .catch(e => {
59
+ this.logger.logError(e);
60
+ return [];
61
+ });
62
+ return status.reduce((acc, row) => {
63
+ acc[row.origin].push(this.toSyncStatusRow(row));
64
+ return acc;
65
+ }, initValue);
66
+ }));
67
+ });
68
+ }
69
+ deployAndUpdateSourceTracking(paths) {
70
+ return __awaiter(this, void 0, void 0, function* () {
71
+ return yield this.withWorkingDir(this.options.projectDir, () => __awaiter(this, void 0, void 0, function* () {
72
+ return this.deploy(paths)
73
+ .then(res => this.updateSourceTracking(res))
74
+ .catch(e => this.logger.logError(e));
75
+ }));
76
+ });
77
+ }
78
+ deploy(paths) {
79
+ return __awaiter(this, void 0, void 0, function* () {
80
+ const set = source_deploy_retrieve_1.ComponentSet.fromSource(paths);
81
+ const deploy = yield set.deploy({
82
+ usernameOrConnection: this.options.connection,
83
+ });
84
+ this.logger.logDeployProgress('Starting deploy');
85
+ deploy.onUpdate(response => {
86
+ const { status, numberComponentsDeployed, numberComponentsTotal, } = response;
87
+ const progress = `${numberComponentsDeployed}/${numberComponentsTotal}`;
88
+ const message = `Status: ${status} Progress: ${progress}`;
89
+ this.logger.logDeployProgress(message);
90
+ });
91
+ return yield deploy.pollStatus().then(res => {
92
+ this.logger.logMessage('Finished deploy');
93
+ return res;
94
+ });
95
+ });
96
+ }
97
+ updateSourceTracking(result) {
98
+ return __awaiter(this, void 0, void 0, function* () {
99
+ const project = core_1.SfProject.getInstance(this.options.projectDir);
100
+ const org = yield core_1.Org.create({ connection: this.options.connection });
101
+ const tracking = yield source_tracking_1.SourceTracking.create({
102
+ org,
103
+ project,
104
+ ignoreLocalCache: true,
105
+ });
106
+ yield tracking.updateTrackingFromDeploy(result);
107
+ });
108
+ }
109
+ toSyncStatusRow(from) {
110
+ const state = [];
111
+ if (from.ignored) {
112
+ state.push(FileState.Ignored);
113
+ }
114
+ if (from.conflict) {
115
+ state.push(FileState.Conflicted);
116
+ }
117
+ state.push(from.state);
118
+ return {
119
+ fullName: from.fullName,
120
+ path: from.filePath,
121
+ state: state,
122
+ type: from.type,
123
+ origin: from.origin,
124
+ };
125
+ }
126
+ withWorkingDir(path, op) {
127
+ return __awaiter(this, void 0, void 0, function* () {
128
+ const startDir = (0, process_1.cwd)();
129
+ (0, process_1.chdir)(path);
130
+ try {
131
+ return yield op();
132
+ }
133
+ finally {
134
+ (0, process_1.chdir)(startDir);
135
+ }
136
+ });
137
+ }
138
+ }
139
+ exports.OrgTracking = OrgTracking;
@@ -1,3 +1,5 @@
1
1
  export { getDefaultBranchDiff, getDefaultBranchDiffByRef, getDiffRange, getLocalChanges, } from './FilesChanged/BranchChanges';
2
+ export { OrgTracking, OrgTrackingOptions, FileState, SyncStatusRow, SyncStatus, } from './OrgTracking/Tracking';
3
+ export { Logger } from './logger/Logger';
2
4
  export { IGit } from './api/IGit';
3
5
  export { Git } from './Git/Git';
package/lib/src/index.js CHANGED
@@ -3,11 +3,14 @@
3
3
  * Copyright (c) 2023, FinancialForce.com, inc. All rights reserved.
4
4
  */
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.Git = exports.getLocalChanges = exports.getDiffRange = exports.getDefaultBranchDiffByRef = exports.getDefaultBranchDiff = void 0;
6
+ exports.Git = exports.FileState = exports.OrgTracking = exports.getLocalChanges = exports.getDiffRange = exports.getDefaultBranchDiffByRef = exports.getDefaultBranchDiff = void 0;
7
7
  var BranchChanges_1 = require("./FilesChanged/BranchChanges");
8
8
  Object.defineProperty(exports, "getDefaultBranchDiff", { enumerable: true, get: function () { return BranchChanges_1.getDefaultBranchDiff; } });
9
9
  Object.defineProperty(exports, "getDefaultBranchDiffByRef", { enumerable: true, get: function () { return BranchChanges_1.getDefaultBranchDiffByRef; } });
10
10
  Object.defineProperty(exports, "getDiffRange", { enumerable: true, get: function () { return BranchChanges_1.getDiffRange; } });
11
11
  Object.defineProperty(exports, "getLocalChanges", { enumerable: true, get: function () { return BranchChanges_1.getLocalChanges; } });
12
+ var Tracking_1 = require("./OrgTracking/Tracking");
13
+ Object.defineProperty(exports, "OrgTracking", { enumerable: true, get: function () { return Tracking_1.OrgTracking; } });
14
+ Object.defineProperty(exports, "FileState", { enumerable: true, get: function () { return Tracking_1.FileState; } });
12
15
  var Git_1 = require("./Git/Git");
13
16
  Object.defineProperty(exports, "Git", { enumerable: true, get: function () { return Git_1.Git; } });
@@ -0,0 +1,5 @@
1
+ export interface Logger {
2
+ logError(error: any): void;
3
+ logMessage(message: any): void;
4
+ logDeployProgress(status: string): void;
5
+ }
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright (c) 2023 Certinia Inc. All rights reserved.
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -28,37 +28,62 @@ describe('Git', () => {
28
28
  yield repoManager.tearDown();
29
29
  }));
30
30
  describe('version check', () => {
31
- it('does not fail when Git version is equal to 2.30.0', () => {
31
+ it('does not fail when Git version is equal to 2.20.0', () => {
32
32
  //Given/When
33
33
  const mock = {
34
- version: jest.fn().mockReturnValue({ major: 2, minor: 30, patch: 0 }),
34
+ version: jest.fn().mockReturnValue({
35
+ installed: true,
36
+ major: 2,
37
+ minor: 20,
38
+ patch: 0,
39
+ }),
35
40
  };
36
41
  expect(Git_1.Git.versionCheck(mock)).resolves;
37
42
  });
38
- it('fails when Git major version is lower', () => __awaiter(void 0, void 0, void 0, function* () {
43
+ it('does not fail when Git version is higher', () => {
44
+ //Given/When
45
+ const mock = {
46
+ version: jest.fn().mockReturnValue({
47
+ installed: true,
48
+ major: 2,
49
+ minor: 30,
50
+ patch: 2,
51
+ }),
52
+ };
53
+ //Then
54
+ expect(Git_1.Git.versionCheck(mock)).resolves;
55
+ });
56
+ it('fails when Git is not installed', () => __awaiter(void 0, void 0, void 0, function* () {
39
57
  //Given/When
40
58
  const mock = {
41
- version: jest.fn().mockReturnValue({ major: 1 }),
59
+ version: jest.fn().mockReturnValue({ installed: false }),
42
60
  };
43
61
  //Then
44
- yield expect(Git_1.Git.versionCheck(mock)).rejects.toThrow(Error('Unsupported version of git. Min version must be 2.30.0'));
62
+ yield expect(Git_1.Git.versionCheck(mock)).rejects.toThrow(Error('"git" is not installed or available on the PATH'));
45
63
  }));
46
- it('fails when Git minor version is lower', () => __awaiter(void 0, void 0, void 0, function* () {
64
+ it('fails when Git major version is lower', () => __awaiter(void 0, void 0, void 0, function* () {
47
65
  //Given/When
48
66
  const mock = {
49
- version: jest.fn().mockReturnValue({ major: 3, minor: 36 }),
67
+ version: jest.fn().mockReturnValue({
68
+ installed: true,
69
+ major: 1,
70
+ }),
50
71
  };
51
72
  //Then
52
- yield expect(Git_1.Git.versionCheck(mock)).rejects.toThrow(Error('Unsupported version of git. Min version must be 2.30.0'));
73
+ yield expect(Git_1.Git.versionCheck(mock)).rejects.toThrow(Error('Unsupported version of git. Min version must be 2.20'));
53
74
  }));
54
- it('fails when Git patch version is more than 0', () => {
75
+ it('fails when Git minor version is lower', () => __awaiter(void 0, void 0, void 0, function* () {
55
76
  //Given/When
56
77
  const mock = {
57
- version: jest.fn().mockReturnValue({ major: 3, minor: 38, patch: 1 }),
78
+ version: jest.fn().mockReturnValue({
79
+ installed: true,
80
+ major: 2,
81
+ minor: 19,
82
+ }),
58
83
  };
59
84
  //Then
60
- expect(Git_1.Git.versionCheck(mock)).resolves;
61
- });
85
+ yield expect(Git_1.Git.versionCheck(mock)).rejects.toThrow(Error('Unsupported version of git. Min version must be 2.20'));
86
+ }));
62
87
  });
63
88
  describe('rev parse', () => {
64
89
  it('get git root', () => __awaiter(void 0, void 0, void 0, function* () {
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,312 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright (c) 2023 Certinia Inc. All rights reserved.
4
+ */
5
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
6
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
7
+ return new (P || (P = Promise))(function (resolve, reject) {
8
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
9
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
10
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
11
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
12
+ });
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const src_1 = require("../../src");
16
+ const core_1 = require("@salesforce/core");
17
+ const mockGetStatusData = [
18
+ {
19
+ fullName: 'SomeComponent',
20
+ filePath: 'path/to/file',
21
+ type: 'class',
22
+ origin: 'local',
23
+ ignored: false,
24
+ conflict: false,
25
+ state: 'add',
26
+ },
27
+ {
28
+ fullName: 'SomeComponent1',
29
+ filePath: 'path/to/file/1',
30
+ type: 'class',
31
+ origin: 'local',
32
+ ignored: false,
33
+ conflict: true,
34
+ state: 'delete',
35
+ },
36
+ {
37
+ fullName: 'SomeComponent2',
38
+ filePath: 'path/to/file/2',
39
+ type: 'class',
40
+ origin: 'local',
41
+ ignored: true,
42
+ conflict: false,
43
+ state: 'modify',
44
+ },
45
+ {
46
+ fullName: 'SomeComponent3',
47
+ filePath: 'path/to/file/3',
48
+ type: 'class',
49
+ origin: 'local',
50
+ ignored: true,
51
+ conflict: true,
52
+ state: 'nondelete',
53
+ },
54
+ {
55
+ fullName: 'NoPathComponent',
56
+ filePath: undefined,
57
+ type: 'metadata',
58
+ origin: 'local',
59
+ ignored: false,
60
+ conflict: false,
61
+ state: 'add',
62
+ },
63
+ ];
64
+ const mockConflictsData = [
65
+ {
66
+ filenames: [
67
+ 'path/to/file',
68
+ 'path/to/file/3',
69
+ { nonString: 'object' },
70
+ 'path/to/file/non/existent',
71
+ ],
72
+ },
73
+ ];
74
+ jest.mock('@salesforce/core', () => {
75
+ return {
76
+ SfProject: { getInstance: jest.fn() },
77
+ Org: { create: jest.fn() },
78
+ };
79
+ });
80
+ const mockConnection = jest.fn();
81
+ const mockSourceTracking = {
82
+ ensureRemoteTracking: jest.fn(),
83
+ getStatus: jest
84
+ .fn()
85
+ .mockImplementation(() => Promise.resolve(mockGetStatusData)),
86
+ getConflicts: jest
87
+ .fn()
88
+ .mockImplementation(() => Promise.resolve(mockConflictsData)),
89
+ updateTrackingFromDeploy: jest
90
+ .fn()
91
+ .mockImplementation(() => Promise.resolve()),
92
+ };
93
+ jest.mock('@salesforce/source-tracking', () => {
94
+ return {
95
+ SourceTracking: {
96
+ create: jest
97
+ .fn()
98
+ .mockImplementation(() => Promise.resolve(Object.assign({}, mockSourceTracking))),
99
+ },
100
+ };
101
+ });
102
+ const mockDeploy = {
103
+ onUpdate: jest.fn(),
104
+ pollStatus: jest
105
+ .fn()
106
+ .mockImplementation(() => Promise.resolve(mockDeployResult)),
107
+ };
108
+ const mockDeployResult = { done: true };
109
+ const mockComponentSet = {
110
+ deploy: jest
111
+ .fn()
112
+ .mockImplementation(() => Promise.resolve(Object.assign({}, mockDeploy))),
113
+ };
114
+ jest.mock('@salesforce/source-deploy-retrieve', () => {
115
+ return {
116
+ ComponentSet: {
117
+ fromSource: jest.fn().mockImplementation(() => {
118
+ return Object.assign({}, mockComponentSet);
119
+ }),
120
+ },
121
+ };
122
+ });
123
+ describe('OrgTracking', () => {
124
+ const PROJECT_DIR = 'path/to/dir';
125
+ let cwdSpy, chdirSpy;
126
+ const sfCoreSpy = {
127
+ SfProject: { getInstance: jest.spyOn(core_1.SfProject, 'getInstance') },
128
+ Org: { create: jest.spyOn(core_1.Org, 'create') },
129
+ };
130
+ beforeEach(() => {
131
+ jest.mock('process');
132
+ cwdSpy = jest
133
+ .spyOn(process, 'cwd')
134
+ .mockImplementation(() => 'mocked/current/working/dir');
135
+ chdirSpy = jest.spyOn(process, 'chdir').mockImplementation(() => {
136
+ return;
137
+ });
138
+ });
139
+ afterEach(() => {
140
+ jest.clearAllMocks();
141
+ });
142
+ const mockLogger = {
143
+ logDeployProgress: jest.fn(),
144
+ logError: jest.fn(),
145
+ logMessage: jest.fn(),
146
+ };
147
+ describe('getLocalStatus', () => {
148
+ it('returns the correct status', () => __awaiter(void 0, void 0, void 0, function* () {
149
+ const tracking = new src_1.OrgTracking({
150
+ connection: mockConnection,
151
+ projectDir: PROJECT_DIR,
152
+ logger: mockLogger,
153
+ });
154
+ const res = yield tracking.getLocalStatus();
155
+ expect(cwdSpy).toHaveBeenCalled();
156
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
157
+ expect(chdirSpy.mock.calls).toEqual([
158
+ [PROJECT_DIR],
159
+ ['mocked/current/working/dir'],
160
+ ]);
161
+ expect(sfCoreSpy.Org.create).toHaveBeenCalledWith({
162
+ connection: mockConnection,
163
+ });
164
+ expect(sfCoreSpy.SfProject.getInstance).toHaveBeenCalledWith(PROJECT_DIR);
165
+ expect(mockSourceTracking.ensureRemoteTracking).toHaveBeenCalledWith(true);
166
+ expect(mockSourceTracking.getStatus).toHaveBeenCalledWith({
167
+ local: true,
168
+ remote: false,
169
+ });
170
+ expect(mockSourceTracking.getConflicts).not.toBeCalled();
171
+ expect(res).toEqual({
172
+ local: [
173
+ {
174
+ fullName: 'SomeComponent',
175
+ origin: 'local',
176
+ path: 'path/to/file',
177
+ state: ['add'],
178
+ type: 'class',
179
+ },
180
+ {
181
+ fullName: 'SomeComponent1',
182
+ origin: 'local',
183
+ path: 'path/to/file/1',
184
+ state: ['conflict', 'delete'],
185
+ type: 'class',
186
+ },
187
+ {
188
+ fullName: 'SomeComponent2',
189
+ origin: 'local',
190
+ path: 'path/to/file/2',
191
+ state: ['ignore', 'modify'],
192
+ type: 'class',
193
+ },
194
+ {
195
+ fullName: 'SomeComponent3',
196
+ origin: 'local',
197
+ path: 'path/to/file/3',
198
+ state: ['ignore', 'conflict', 'nondelete'],
199
+ type: 'class',
200
+ },
201
+ {
202
+ fullName: 'NoPathComponent',
203
+ path: undefined,
204
+ type: 'metadata',
205
+ origin: 'local',
206
+ state: ['add'],
207
+ },
208
+ ],
209
+ remote: [],
210
+ });
211
+ }));
212
+ it('returns the correct status with conflicts', () => __awaiter(void 0, void 0, void 0, function* () {
213
+ //Given
214
+ const tracking = new src_1.OrgTracking({
215
+ connection: mockConnection,
216
+ projectDir: PROJECT_DIR,
217
+ logger: mockLogger,
218
+ });
219
+ //When
220
+ const res = yield tracking.getLocalStatus(true);
221
+ //Then
222
+ expect(cwdSpy).toHaveBeenCalled();
223
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
224
+ expect(chdirSpy.mock.calls).toEqual([
225
+ [PROJECT_DIR],
226
+ ['mocked/current/working/dir'],
227
+ ]);
228
+ expect(sfCoreSpy.Org.create).toHaveBeenCalledWith({
229
+ connection: mockConnection,
230
+ });
231
+ expect(sfCoreSpy.SfProject.getInstance).toHaveBeenCalledWith(PROJECT_DIR);
232
+ expect(mockSourceTracking.ensureRemoteTracking).toHaveBeenCalledWith(true);
233
+ expect(mockSourceTracking.getStatus).toHaveBeenCalledWith({
234
+ local: true,
235
+ remote: false,
236
+ });
237
+ expect(mockSourceTracking.getConflicts).toBeCalled();
238
+ expect(res).toEqual({
239
+ local: [
240
+ {
241
+ fullName: 'SomeComponent',
242
+ origin: 'local',
243
+ path: 'path/to/file',
244
+ state: ['conflict', 'add'],
245
+ type: 'class',
246
+ },
247
+ {
248
+ fullName: 'SomeComponent1',
249
+ origin: 'local',
250
+ path: 'path/to/file/1',
251
+ state: ['delete'],
252
+ type: 'class',
253
+ },
254
+ {
255
+ fullName: 'SomeComponent2',
256
+ origin: 'local',
257
+ path: 'path/to/file/2',
258
+ state: ['ignore', 'modify'],
259
+ type: 'class',
260
+ },
261
+ {
262
+ fullName: 'SomeComponent3',
263
+ origin: 'local',
264
+ path: 'path/to/file/3',
265
+ state: ['ignore', 'conflict', 'nondelete'],
266
+ type: 'class',
267
+ },
268
+ {
269
+ fullName: 'NoPathComponent',
270
+ origin: 'local',
271
+ path: undefined,
272
+ state: ['add'],
273
+ type: 'metadata',
274
+ },
275
+ ],
276
+ remote: [],
277
+ });
278
+ }));
279
+ });
280
+ describe('deployAndUpdateSourceTracking', () => {
281
+ it('deploys and update tracking given paths', () => __awaiter(void 0, void 0, void 0, function* () {
282
+ //Given
283
+ const paths = ['/path/to/component', '/path/to/component/1'];
284
+ const tracking = new src_1.OrgTracking({
285
+ connection: mockConnection,
286
+ projectDir: PROJECT_DIR,
287
+ logger: mockLogger,
288
+ });
289
+ //When
290
+ yield tracking.deployAndUpdateSourceTracking(paths);
291
+ //Then
292
+ expect(cwdSpy).toHaveBeenCalled();
293
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
294
+ expect(chdirSpy.mock.calls).toEqual([
295
+ [PROJECT_DIR],
296
+ ['mocked/current/working/dir'],
297
+ ]);
298
+ expect(mockComponentSet.deploy).toHaveBeenCalledWith({
299
+ usernameOrConnection: mockConnection,
300
+ });
301
+ expect(mockDeploy.onUpdate).toHaveBeenCalled();
302
+ expect(mockDeploy.pollStatus).toHaveBeenCalled();
303
+ expect(sfCoreSpy.Org.create).toHaveBeenCalledWith({
304
+ connection: mockConnection,
305
+ });
306
+ expect(sfCoreSpy.SfProject.getInstance).toHaveBeenCalledWith(PROJECT_DIR);
307
+ expect(mockSourceTracking.updateTrackingFromDeploy).toHaveBeenCalledWith(mockDeployResult);
308
+ // eslint-disable-next-line @typescript-eslint/unbound-method
309
+ expect(mockLogger.logDeployProgress).toBeCalledWith('Starting deploy');
310
+ }));
311
+ });
312
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@apexdevtools/git-ops",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "Library to do git operations to find changed files in a given git repository",
5
5
  "author": {
6
6
  "name": "Apex Dev Tools Team",
@@ -50,7 +50,9 @@
50
50
  "typescript": "^4.9.5"
51
51
  },
52
52
  "dependencies": {
53
- "install": "^0.13.0",
53
+ "@salesforce/core": "^3.36.1",
54
+ "@salesforce/source-deploy-retrieve": "8.6.0",
55
+ "@salesforce/source-tracking": "3.1.2",
54
56
  "simple-git": "^3.16.0"
55
57
  },
56
58
  "config": {