@apexdevtools/git-ops 1.1.1 → 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 +7 -0
- package/lib/src/Git/Git.d.ts +0 -1
- package/lib/src/Git/Git.js +2 -4
- package/lib/src/OrgTracking/Tracking.d.ts +37 -0
- package/lib/src/OrgTracking/Tracking.js +139 -0
- package/lib/src/index.d.ts +2 -0
- package/lib/src/index.js +4 -1
- package/lib/src/logger/Logger.d.ts +5 -0
- package/lib/src/logger/Logger.js +5 -0
- package/lib/test/Git/Git.spec.js +2 -2
- package/lib/test/OrgTracking/Tracking.spec.d.ts +1 -0
- package/lib/test/OrgTracking/Tracking.spec.js +312 -0
- package/package.json +4 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
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
|
+
|
|
3
10
|
## 1.1.1 - 2023-03-27
|
|
4
11
|
|
|
5
12
|
- Update minimum version to 2.20.0
|
package/lib/src/Git/Git.d.ts
CHANGED
|
@@ -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);
|
package/lib/src/Git/Git.js
CHANGED
|
@@ -36,13 +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;
|
|
41
40
|
if (!version.installed) {
|
|
42
41
|
throw new Error('"git" is not installed or available on the PATH');
|
|
43
42
|
}
|
|
44
43
|
if (!isSupported)
|
|
45
|
-
throw new Error(`Unsupported version of git. Min version must be ${this.MIN_GIT_VERSION_MAJOR}.${this.MIN_GIT_VERSION_MINOR}
|
|
44
|
+
throw new Error(`Unsupported version of git. Min version must be ${this.MIN_GIT_VERSION_MAJOR}.${this.MIN_GIT_VERSION_MINOR}`);
|
|
46
45
|
});
|
|
47
46
|
}
|
|
48
47
|
get git() {
|
|
@@ -109,4 +108,3 @@ class Git {
|
|
|
109
108
|
exports.Git = Git;
|
|
110
109
|
Git.MIN_GIT_VERSION_MAJOR = 2;
|
|
111
110
|
Git.MIN_GIT_VERSION_MINOR = 20;
|
|
112
|
-
Git.MIN_GIT_VERSION_PATCH = 0;
|
|
@@ -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;
|
package/lib/src/index.d.ts
CHANGED
|
@@ -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; } });
|
package/lib/test/Git/Git.spec.js
CHANGED
|
@@ -70,7 +70,7 @@ describe('Git', () => {
|
|
|
70
70
|
}),
|
|
71
71
|
};
|
|
72
72
|
//Then
|
|
73
|
-
yield expect(Git_1.Git.versionCheck(mock)).rejects.toThrow(Error('Unsupported version of git. Min version must be 2.20
|
|
73
|
+
yield expect(Git_1.Git.versionCheck(mock)).rejects.toThrow(Error('Unsupported version of git. Min version must be 2.20'));
|
|
74
74
|
}));
|
|
75
75
|
it('fails when Git minor version is lower', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
76
76
|
//Given/When
|
|
@@ -82,7 +82,7 @@ describe('Git', () => {
|
|
|
82
82
|
}),
|
|
83
83
|
};
|
|
84
84
|
//Then
|
|
85
|
-
yield expect(Git_1.Git.versionCheck(mock)).rejects.toThrow(Error('Unsupported version of git. Min version must be 2.20
|
|
85
|
+
yield expect(Git_1.Git.versionCheck(mock)).rejects.toThrow(Error('Unsupported version of git. Min version must be 2.20'));
|
|
86
86
|
}));
|
|
87
87
|
});
|
|
88
88
|
describe('rev parse', () => {
|
|
@@ -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.
|
|
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,6 +50,9 @@
|
|
|
50
50
|
"typescript": "^4.9.5"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
+
"@salesforce/core": "^3.36.1",
|
|
54
|
+
"@salesforce/source-deploy-retrieve": "8.6.0",
|
|
55
|
+
"@salesforce/source-tracking": "3.1.2",
|
|
53
56
|
"simple-git": "^3.16.0"
|
|
54
57
|
},
|
|
55
58
|
"config": {
|