@ds-sfdc/sfparty 1.3.5 → 1.3.7
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 +1 -1
- package/package.json +2 -1
- package/src/index.js +17 -5
- package/src/lib/checkVersion.js +6 -10
- package/src/lib/gitUtils.js +1 -1
- package/src/lib/packageUtil.js +14 -1
- package/test/{checkVersion.spec.js → lib/checkVersion.spec.js} +37 -11
- package/test/lib/package/getPackageXML.spec.js +112 -1
- /package/test/{root.spec.js → src/root.spec.js} +0 -0
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @ds-sfdc/sfparty
|
|
2
2
|
|
|
3
|
-
[](https://www.npmjs.com/package/@ds-sfdc/sfparty) [](https://npmjs.org/package/@ds-sfdc/sfparty) [](https://github.com/TimPaulaskasDS/sfparty/blob/main/LICENSE.md)
|
|
3
|
+
[](https://www.npmjs.com/package/@ds-sfdc/sfparty) [](https://npmjs.org/package/@ds-sfdc/sfparty) [](https://github.com/TimPaulaskasDS/sfparty/blob/main/LICENSE.md) 
|
|
4
4
|
|
|
5
5
|
## Why use sfparty?
|
|
6
6
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ds-sfdc/sfparty",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.7",
|
|
4
4
|
"description": "Salesforce metadata XML splitter for CI/CD",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
"marked": "^4.2.12",
|
|
34
34
|
"marked-terminal": "^5.1.1",
|
|
35
35
|
"pinst": "^3.0.0",
|
|
36
|
+
"semver": "^7.3.8",
|
|
36
37
|
"util": "^0.10.3",
|
|
37
38
|
"winston": "^3.8.2",
|
|
38
39
|
"xml2js": "^0.4.23",
|
package/src/index.js
CHANGED
|
@@ -139,9 +139,17 @@ yargs(hideBin(process.argv))
|
|
|
139
139
|
.check(yargCheck)
|
|
140
140
|
},
|
|
141
141
|
handler: (argv) => {
|
|
142
|
-
checkVersion(axios, spawnSync, pkgObj.default.version, true)
|
|
142
|
+
checkVersion({axios, spawnSync, currentVersion: pkgObj.default.version, update: true})
|
|
143
143
|
}
|
|
144
144
|
})
|
|
145
|
+
.command({
|
|
146
|
+
command: '[version]',
|
|
147
|
+
alias: 'version',
|
|
148
|
+
builder: (yargs) => {
|
|
149
|
+
yargs
|
|
150
|
+
.check(yargCheck)
|
|
151
|
+
},
|
|
152
|
+
})
|
|
145
153
|
.command({
|
|
146
154
|
command: '[split]',
|
|
147
155
|
alias: 'split',
|
|
@@ -154,7 +162,7 @@ yargs(hideBin(process.argv))
|
|
|
154
162
|
.check(yargCheck)
|
|
155
163
|
},
|
|
156
164
|
handler: (argv) => {
|
|
157
|
-
checkVersion(axios, spawnSync, pkgObj.default.version)
|
|
165
|
+
checkVersion({axios, spawnSync, currentVersion: pkgObj.default.version})
|
|
158
166
|
global.format = argv.format
|
|
159
167
|
splitHandler(argv, processStartTime)
|
|
160
168
|
}
|
|
@@ -171,7 +179,7 @@ yargs(hideBin(process.argv))
|
|
|
171
179
|
.check(yargCheck)
|
|
172
180
|
},
|
|
173
181
|
handler: (argv) => {
|
|
174
|
-
checkVersion(axios, spawnSync, pkgObj.default.version)
|
|
182
|
+
checkVersion({axios, spawnSync, currentVersion: pkgObj.default.version})
|
|
175
183
|
global.format = argv.format
|
|
176
184
|
const startProm = new Promise((resolve, reject) => {
|
|
177
185
|
if (argv.git !== undefined) {
|
|
@@ -253,6 +261,10 @@ function yargCheck(argv, options) {
|
|
|
253
261
|
!options.array.includes(key)
|
|
254
262
|
)
|
|
255
263
|
|
|
264
|
+
if (!argv._.includes('update')) {
|
|
265
|
+
checkVersion({axios, spawnSync, currentVersion: pkgObj.default.version, update: false})
|
|
266
|
+
}
|
|
267
|
+
|
|
256
268
|
if (invalidKeys.length > 0) {
|
|
257
269
|
const invalidKeysWithColor = invalidKeys.map(key => clc.redBright(key))
|
|
258
270
|
throw new Error(`Invalid options specified: ${invalidKeysWithColor.join(', ')}`)
|
|
@@ -547,8 +559,8 @@ function processCombine(typeItem, argv) {
|
|
|
547
559
|
|
|
548
560
|
function gitFiles(data) {
|
|
549
561
|
data.forEach(item => {
|
|
550
|
-
if (item.path.indexOf(packageDir + '-party'
|
|
551
|
-
const pathArray = item.path.split(
|
|
562
|
+
if (item.path.indexOf(packageDir + '-party/') == 0) {
|
|
563
|
+
const pathArray = item.path.split('/')
|
|
552
564
|
if (pathArray.length > 3) {
|
|
553
565
|
if (getDirectories().includes(pathArray[3])) {
|
|
554
566
|
switch (item.action) {
|
package/src/lib/checkVersion.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import clc from 'cli-color'
|
|
2
|
+
import semver from 'semver'
|
|
2
3
|
|
|
3
4
|
class NpmNotInstalledError extends Error {
|
|
4
5
|
constructor(message) {
|
|
@@ -21,14 +22,15 @@ class UpdateError extends Error {
|
|
|
21
22
|
}
|
|
22
23
|
}
|
|
23
24
|
|
|
24
|
-
export async function checkVersion(axios, spawnSync, currentVersion, update = false) {
|
|
25
|
+
export async function checkVersion({axios, spawnSync, currentVersion, update = false}) {
|
|
25
26
|
try {
|
|
26
27
|
const { data } = await axios.get('https://registry.npmjs.org/@ds-sfdc/sfparty', {
|
|
27
28
|
params: {
|
|
28
29
|
field: 'dist-tags.latest'
|
|
29
30
|
}
|
|
30
31
|
})
|
|
31
|
-
|
|
32
|
+
const latestVersion = data['dist-tags'].latest
|
|
33
|
+
if (semver.gt(latestVersion, currentVersion)) {
|
|
32
34
|
let icon
|
|
33
35
|
const version = clc.bgCyanBright(data['dist-tags'].latest)
|
|
34
36
|
if (update) {
|
|
@@ -41,11 +43,11 @@ export async function checkVersion(axios, spawnSync, currentVersion, update = fa
|
|
|
41
43
|
console.log(`Please upgrade by running ${clc.cyanBright('sfparty update')}`)
|
|
42
44
|
return 'A newer version'
|
|
43
45
|
} else {
|
|
44
|
-
let command = 'npm i -g @ds-sfdc/sfparty'.split(' ')
|
|
46
|
+
let command = 'npm i -g @ds-sfdc/sfparty@latest'.split(' ')
|
|
45
47
|
console.log(`Updating the application using ${clc.cyanBright(command.join(' '))}`)
|
|
46
48
|
try {
|
|
47
49
|
const npmVersion = spawnSync('npm', ['-v'])
|
|
48
|
-
if (npmVersion.stderr.toString().trim() === 'command not found') {
|
|
50
|
+
if (npmVersion.stderr && npmVersion.stderr.toString().trim() === 'command not found') {
|
|
49
51
|
throw new NpmNotInstalledError("npm is not installed on this system. Please install npm and run the command again.")
|
|
50
52
|
}
|
|
51
53
|
const update = spawnSync(command[0], command.slice(1))
|
|
@@ -54,11 +56,6 @@ export async function checkVersion(axios, spawnSync, currentVersion, update = fa
|
|
|
54
56
|
}
|
|
55
57
|
console.log("Application updated successfully.")
|
|
56
58
|
} catch (err) {
|
|
57
|
-
if (err instanceof NpmNotInstalledError) {
|
|
58
|
-
console.error(err)
|
|
59
|
-
} else if (err instanceof UpdateError) {
|
|
60
|
-
console.error(err)
|
|
61
|
-
}
|
|
62
59
|
throw err
|
|
63
60
|
}
|
|
64
61
|
}
|
|
@@ -72,7 +69,6 @@ export async function checkVersion(axios, spawnSync, currentVersion, update = fa
|
|
|
72
69
|
if (error.response && error.response.status === 404) {
|
|
73
70
|
error = new PackageNotFoundError("Package not found on the npm registry")
|
|
74
71
|
}
|
|
75
|
-
console.error(error)
|
|
76
72
|
throw error
|
|
77
73
|
}
|
|
78
74
|
}
|
package/src/lib/gitUtils.js
CHANGED
|
@@ -57,7 +57,7 @@ export function diff(dir, gitRef = 'HEAD', existsSyncStub = existsSync, execSync
|
|
|
57
57
|
|
|
58
58
|
let data = ''
|
|
59
59
|
try {
|
|
60
|
-
data = execSyncStub(`git diff --name-status --oneline --relative ${gitRef}
|
|
60
|
+
data = execSyncStub(`git diff --name-status --oneline --relative ${gitRef} -- *-party/*`, { cwd: dir, maxBuffer: 1024 * 1024 * 10 }).toString()
|
|
61
61
|
} catch (error) {
|
|
62
62
|
reject(error)
|
|
63
63
|
}
|
package/src/lib/packageUtil.js
CHANGED
|
@@ -25,7 +25,6 @@ export class Package {
|
|
|
25
25
|
processJSON(that, json, fileUtils)
|
|
26
26
|
resolve('existing')
|
|
27
27
|
} catch (error) {
|
|
28
|
-
console.error(error)
|
|
29
28
|
reject(error)
|
|
30
29
|
}
|
|
31
30
|
})
|
|
@@ -55,6 +54,20 @@ export class Package {
|
|
|
55
54
|
}
|
|
56
55
|
that.packageJSON = json
|
|
57
56
|
if (json.Package.types !== undefined) transformJSON(json.Package.types)
|
|
57
|
+
cleanPackage(that)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function cleanPackage(that) {
|
|
61
|
+
if (that.packageJSON === undefined) throw new Error('getPackageXML must be called before adding members')
|
|
62
|
+
if (that.packageJSON.Package == undefined) throw new Error('Package initialization failed')
|
|
63
|
+
if (that.packageJSON.Package.types === undefined) return 'No types found'
|
|
64
|
+
|
|
65
|
+
const typeArray = Object.values(global.metaTypes).map(metaType => metaType.definition.root);
|
|
66
|
+
that.packageJSON.Package.types.forEach(typeItem => {
|
|
67
|
+
if (typeArray.includes(typeItem.name)) {
|
|
68
|
+
typeItem.members = typeItem.members.filter(member => !member.endsWith(`.${global.format}`))
|
|
69
|
+
}
|
|
70
|
+
})
|
|
58
71
|
}
|
|
59
72
|
}
|
|
60
73
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import axios from 'axios'
|
|
2
2
|
import { spawnSync } from 'child_process'
|
|
3
3
|
import clc from 'cli-color'
|
|
4
|
-
import { checkVersion } from '
|
|
4
|
+
import { checkVersion } from '../../src/lib/checkVersion.js'
|
|
5
5
|
|
|
6
6
|
global.icons = {
|
|
7
7
|
"success": clc.greenBright('✔'),
|
|
@@ -24,46 +24,72 @@ describe('checkVersion', () => {
|
|
|
24
24
|
|
|
25
25
|
it('should return "A newer version" if a newer version is available', async () => {
|
|
26
26
|
axios.get.mockResolvedValue({ data: { 'dist-tags': { latest: '2.0.0' } } })
|
|
27
|
-
const result = await checkVersion(axios, spawnSync, '1.0.0')
|
|
27
|
+
const result = await checkVersion({axios, spawnSync, currentVersion: '1.0.0'})
|
|
28
28
|
expect(result).toBe('A newer version')
|
|
29
|
-
})
|
|
29
|
+
}, { silent: true })
|
|
30
30
|
|
|
31
31
|
it('should return "You are on the latest version" if the current version is the latest version', async () => {
|
|
32
32
|
axios.get.mockResolvedValue({ data: { 'dist-tags': { latest: '1.0.0' } } })
|
|
33
|
-
const result = await checkVersion(axios, spawnSync, '1.0.0')
|
|
33
|
+
const result = await checkVersion({axios, spawnSync, currentVersion: '1.0.0'})
|
|
34
34
|
expect(result).toBe('You are on the latest version')
|
|
35
|
-
})
|
|
35
|
+
}, { silent: true })
|
|
36
36
|
|
|
37
37
|
it('should throw a NpmNotInstalledError if npm is not installed', async () => {
|
|
38
38
|
axios.get.mockResolvedValue({ data: { 'dist-tags': { latest: '2.0.0' } } })
|
|
39
39
|
spawnSync.mockReturnValue({ status: 1, stderr: { toString: () => 'command not found' } })
|
|
40
40
|
try {
|
|
41
|
-
await checkVersion(axios, spawnSync, '1.0.0', true)
|
|
41
|
+
await checkVersion({axios, spawnSync, currentVersion: '1.0.0', update: true})
|
|
42
42
|
} catch (err) {
|
|
43
43
|
expect(err.name).toBe('NpmNotInstalledError')
|
|
44
44
|
expect(err.message).toBe('npm is not installed on this system. Please install npm and run the command again.')
|
|
45
45
|
}
|
|
46
|
-
})
|
|
46
|
+
}, { silent: true })
|
|
47
47
|
|
|
48
48
|
it('should throw a PackageNotFoundError if the package is not found on the npm registry', async () => {
|
|
49
49
|
axios.get.mockRejectedValue({ response: { status: 404 } });
|
|
50
50
|
try {
|
|
51
|
-
await checkVersion(axios, spawnSync, '1.0.0');
|
|
51
|
+
await checkVersion({axios, spawnSync, currentVersion: '1.0.0'});
|
|
52
52
|
} catch (err) {
|
|
53
53
|
expect(err.name).toBe('PackageNotFoundError');
|
|
54
54
|
expect(err.message).toBe('Package not found on the npm registry');
|
|
55
55
|
}
|
|
56
|
-
});
|
|
56
|
+
}, { silent: true });
|
|
57
57
|
|
|
58
58
|
it('should throw a UpdateError if an error occurs while updating the package', async () => {
|
|
59
59
|
axios.get.mockResolvedValue({ data: { 'dist-tags': { latest: '2.0.0' } } });
|
|
60
60
|
spawnSync.mockReturnValue({ status: 1, stderr: { toString: () => 'Update error' } });
|
|
61
61
|
try {
|
|
62
|
-
await checkVersion(axios, spawnSync, '1.0.0', true);
|
|
62
|
+
await checkVersion({axios, spawnSync, currentVersion: '1.0.0', update: true});
|
|
63
|
+
} catch (err) {
|
|
64
|
+
expect(err.name).toBe('UpdateError');
|
|
65
|
+
expect(err.message).toBe('Error updating the application.');
|
|
66
|
+
}
|
|
67
|
+
}, { silent: true });
|
|
68
|
+
|
|
69
|
+
it('should throw a UpdateError if update.status !== 0', async () => {
|
|
70
|
+
axios.get.mockResolvedValue({ data: { 'dist-tags': { latest: '2.0.0' } } });
|
|
71
|
+
spawnSync.mockImplementationOnce(() => ({ status: 0 }));
|
|
72
|
+
spawnSync.mockImplementationOnce(() => ({ status: 1, stderr: { toString: () => 'Update error' } }));
|
|
73
|
+
try {
|
|
74
|
+
await checkVersion({axios, spawnSync, currentVersion: '1.0.0', update: true});
|
|
63
75
|
} catch (err) {
|
|
64
76
|
expect(err.name).toBe('UpdateError');
|
|
65
77
|
expect(err.message).toBe('Error updating the application.');
|
|
66
78
|
}
|
|
67
|
-
});
|
|
79
|
+
}, { silent: true });
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
it('should log "You are on the latest version" if update flag is true and the current version is the latest version', async () => {
|
|
83
|
+
axios.get.mockResolvedValue({ data: { 'dist-tags': { latest: '1.0.0' } } });
|
|
84
|
+
await checkVersion({axios, spawnSync, currentVersion: '1.0.0', update: true});
|
|
85
|
+
expect(console.log).toHaveBeenCalledWith(`${global.icons.success} You are on the latest version.`);
|
|
86
|
+
}, { silent: true });
|
|
87
|
+
|
|
88
|
+
it('should log "Application updated successfully." after successful update', async () => {
|
|
89
|
+
axios.get.mockResolvedValue({ data: { 'dist-tags': { latest: '2.0.0' } } });
|
|
90
|
+
spawnSync.mockReturnValue({ status: 0 });
|
|
91
|
+
await checkVersion({axios, spawnSync, currentVersion: '1.0.0', update: true});
|
|
92
|
+
expect(console.log).toHaveBeenCalledWith("Application updated successfully.");
|
|
93
|
+
}, { silent: true });
|
|
68
94
|
|
|
69
95
|
})
|
|
@@ -1,5 +1,39 @@
|
|
|
1
|
+
|
|
1
2
|
import * as packageDefinition from '../../../src/meta/Package.js'
|
|
2
3
|
import { Package } from '../../../src/lib/packageUtil.js'
|
|
4
|
+
import * as labelDefinition from '../../../src/meta/CustomLabels.js'
|
|
5
|
+
import * as profileDefinition from '../../../src/meta/Profiles.js'
|
|
6
|
+
import * as permsetDefinition from '../../../src/meta/PermissionSets.js'
|
|
7
|
+
import * as workflowDefinition from '../../../src/meta/Workflows.js'
|
|
8
|
+
|
|
9
|
+
global.__basedir = '.'
|
|
10
|
+
|
|
11
|
+
global.metaTypes = {
|
|
12
|
+
label: {
|
|
13
|
+
type: labelDefinition.metadataDefinition.filetype,
|
|
14
|
+
definition: labelDefinition.metadataDefinition,
|
|
15
|
+
add: { files: [], directories: [] },
|
|
16
|
+
remove: { files: [], directories: [] },
|
|
17
|
+
},
|
|
18
|
+
profile: {
|
|
19
|
+
type: profileDefinition.metadataDefinition.filetype,
|
|
20
|
+
definition: profileDefinition.metadataDefinition,
|
|
21
|
+
add: { files: [], directories: [] },
|
|
22
|
+
remove: { files: [], directories: [] },
|
|
23
|
+
},
|
|
24
|
+
permset: {
|
|
25
|
+
type: permsetDefinition.metadataDefinition.filetype,
|
|
26
|
+
definition: permsetDefinition.metadataDefinition,
|
|
27
|
+
add: { files: [], directories: [] },
|
|
28
|
+
remove: { files: [], directories: [] },
|
|
29
|
+
},
|
|
30
|
+
workflow: {
|
|
31
|
+
type: workflowDefinition.metadataDefinition.filetype,
|
|
32
|
+
definition: workflowDefinition.metadataDefinition,
|
|
33
|
+
add: { files: [], directories: [] },
|
|
34
|
+
remove: { files: [], directories: [] },
|
|
35
|
+
},
|
|
36
|
+
}
|
|
3
37
|
|
|
4
38
|
let pkg;
|
|
5
39
|
const fileUtils = {
|
|
@@ -9,7 +43,8 @@ const fileUtils = {
|
|
|
9
43
|
beforeEach(() => {
|
|
10
44
|
pkg = new Package('xmlPath');
|
|
11
45
|
});
|
|
12
|
-
|
|
46
|
+
|
|
47
|
+
|
|
13
48
|
afterEach(() => {
|
|
14
49
|
jest.clearAllMocks();
|
|
15
50
|
});
|
|
@@ -55,3 +90,79 @@ it('should throw an error if error occurs during processing', async () => {
|
|
|
55
90
|
fileUtils.readFile.mockRejectedValue(new Error('Error'));
|
|
56
91
|
await expect(pkg.getPackageXML(fileUtils)).rejects.toThrowError('Error');
|
|
57
92
|
});
|
|
93
|
+
|
|
94
|
+
it('should catch errors and reject the promise', async () => {
|
|
95
|
+
fileUtils.fileExists.mockReturnValue(true);
|
|
96
|
+
fileUtils.readFile.mockRejectedValue(new Error('Test Error'));
|
|
97
|
+
global.git = { append: true }
|
|
98
|
+
try {
|
|
99
|
+
await pkg.getPackageXML(fileUtils);
|
|
100
|
+
} catch (error) {
|
|
101
|
+
expect(error.message).toEqual('Test Error');
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('should default to an empty package if the read file is empty', async () => {
|
|
106
|
+
fileUtils.fileExists.mockReturnValue(true);
|
|
107
|
+
fileUtils.readFile.mockResolvedValue('');
|
|
108
|
+
global.git = { append: true }
|
|
109
|
+
const result = await pkg.getPackageXML(fileUtils);
|
|
110
|
+
expect(result).toBe('existing');
|
|
111
|
+
expect(pkg.packageJSON).toEqual(packageDefinition.metadataDefinition.emptyPackage);
|
|
112
|
+
expect(fileUtils.fileExists).toHaveBeenCalled();
|
|
113
|
+
expect(fileUtils.readFile).toHaveBeenCalled();
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it('should throw an error if fileUtils.readFile() returns a rejected promise', async () => {
|
|
117
|
+
fileUtils.fileExists.mockReturnValue(true);
|
|
118
|
+
fileUtils.readFile.mockRejectedValue(new Error('Test Error'));
|
|
119
|
+
global.git = { append: true }
|
|
120
|
+
await expect(pkg.getPackageXML(fileUtils)).rejects.toThrowError('Test Error');
|
|
121
|
+
expect(fileUtils.fileExists).toHaveBeenCalled();
|
|
122
|
+
expect(fileUtils.readFile).toHaveBeenCalled();
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('should correctly process the json object returned from the XML file', async () => {
|
|
126
|
+
fileUtils.fileExists.mockReturnValue(true);
|
|
127
|
+
fileUtils.readFile.mockResolvedValue({
|
|
128
|
+
"Package": {
|
|
129
|
+
"types": [{
|
|
130
|
+
"members": ["Test", "Test.yaml"],
|
|
131
|
+
"name": "CustomLabels"
|
|
132
|
+
}, {
|
|
133
|
+
"members": ["Test", "Test.yaml"],
|
|
134
|
+
"name": "Profile"
|
|
135
|
+
}, {
|
|
136
|
+
"members": ["Test", "Test.yaml"],
|
|
137
|
+
"name": "PermissionSet"
|
|
138
|
+
}, {
|
|
139
|
+
"members": ["Test", "Test.yaml"],
|
|
140
|
+
"name": "Workflow"
|
|
141
|
+
}],
|
|
142
|
+
"version": "56.0"
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
global.git = { append: true }
|
|
146
|
+
const result = await pkg.getPackageXML(fileUtils);
|
|
147
|
+
expect(result).toBe('existing');
|
|
148
|
+
expect(fileUtils.fileExists).toHaveBeenCalled();
|
|
149
|
+
expect(fileUtils.readFile).toHaveBeenCalled();
|
|
150
|
+
expect(pkg.packageJSON).toEqual({
|
|
151
|
+
"Package": {
|
|
152
|
+
"types": [{
|
|
153
|
+
"members": ["Test", "Test.yaml"],
|
|
154
|
+
"name": "CustomLabels"
|
|
155
|
+
}, {
|
|
156
|
+
"members": ["Test", "Test.yaml"],
|
|
157
|
+
"name": "Profile"
|
|
158
|
+
}, {
|
|
159
|
+
"members": ["Test", "Test.yaml"],
|
|
160
|
+
"name": "PermissionSet"
|
|
161
|
+
}, {
|
|
162
|
+
"members": ["Test", "Test.yaml"],
|
|
163
|
+
"name": "Workflow"
|
|
164
|
+
}],
|
|
165
|
+
"version": "56.0"
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
});
|
|
File without changes
|