-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #184 from celonis/Buqeta/ta-3012-call-packages-dif…
…f-with-wip-from-content-cli TA-3012: Add diff packages command
- Loading branch information
Showing
8 changed files
with
315 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import {PackageDiffTransport} from "../interfaces/diff-package.transport"; | ||
import {httpClientV2} from "../services/http-client-service.v2"; | ||
import * as FormData from "form-data"; | ||
|
||
class DiffApi { | ||
public static readonly INSTANCE = new DiffApi(); | ||
|
||
public async diffPackages(data: FormData): Promise<PackageDiffTransport[]> { | ||
return httpClientV2.postFile( | ||
"/package-manager/api/core/packages/diff/configuration", | ||
data | ||
); | ||
} | ||
|
||
public async hasChanges(data: FormData): Promise<PackageDiffTransport[]> { | ||
return httpClientV2.postFile( | ||
"/package-manager/api/core/packages/diff/configuration/has-changes", | ||
data | ||
); | ||
} | ||
} | ||
|
||
export const diffApi = DiffApi.INSTANCE; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
export interface ConfigurationChangeTransport { | ||
op: string; | ||
path: string; | ||
from: string; | ||
value: object; | ||
} | ||
|
||
export interface NodeDiffTransport { | ||
nodeKey: string; | ||
changes: ConfigurationChangeTransport[]; | ||
} | ||
|
||
export interface PackageDiffTransport { | ||
packageKey: string; | ||
hasChanges: boolean | ||
packageChanges: ConfigurationChangeTransport[]; | ||
nodesWithChanges: NodeDiffTransport[]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
import * as AdmZip from "adm-zip"; | ||
import {Readable} from "stream"; | ||
import * as FormData from "form-data"; | ||
import {diffApi} from "../../api/diff-api"; | ||
import {FileService, fileService} from "../file-service"; | ||
import {logger} from "../../util/logger"; | ||
import {PackageDiffTransport} from "../../interfaces/diff-package.transport"; | ||
import {v4 as uuidv4} from "uuid"; | ||
|
||
class DiffService { | ||
|
||
public async diffPackages(file: string, hasChanges: boolean, jsonResponse: boolean): Promise<void> { | ||
if (hasChanges) { | ||
await this.hasChanges(file, jsonResponse); | ||
} else { | ||
await this.diffPackagesAndReturnDiff(file, jsonResponse); | ||
} | ||
} | ||
|
||
private async hasChanges(file: string, jsonResponse: boolean): Promise<void> { | ||
const packages = new AdmZip(file); | ||
const formData = this.buildBodyForDiff(packages); | ||
const returnedHasChangesData = await diffApi.hasChanges(formData); | ||
|
||
if (jsonResponse) { | ||
this.exportListOfPackageDiffs(returnedHasChangesData); | ||
} else { | ||
logger.info(this.buildStringResponse(returnedHasChangesData)); | ||
} | ||
} | ||
|
||
private async diffPackagesAndReturnDiff(file: string, jsonResponse: boolean): Promise<void> { | ||
const packages = new AdmZip(file); | ||
const formData = this.buildBodyForDiff(packages); | ||
const returnedHasChangesData = await diffApi.diffPackages(formData); | ||
|
||
if (jsonResponse) { | ||
this.exportListOfPackageDiffs(returnedHasChangesData); | ||
} else { | ||
logger.info(this.buildStringResponse(returnedHasChangesData)); | ||
} | ||
} | ||
|
||
private buildBodyForDiff(packages: AdmZip): FormData { | ||
const formData = new FormData(); | ||
const readableStream = this.getReadableStream(packages); | ||
|
||
formData.append("file", readableStream, {filename: "packages.zip"}); | ||
|
||
return formData; | ||
} | ||
|
||
private getReadableStream(packages: AdmZip): Readable { | ||
return new Readable({ | ||
read(): void { | ||
this.push(packages.toBuffer()); | ||
this.push(null); | ||
} | ||
}); | ||
} | ||
|
||
private exportListOfPackageDiffs(packageDiffs: PackageDiffTransport[]): void { | ||
const filename = uuidv4() + ".json"; | ||
fileService.writeToFileWithGivenName(JSON.stringify(packageDiffs), filename); | ||
logger.info(FileService.fileDownloadedMessage + filename); | ||
} | ||
|
||
private buildStringResponse(packageDiffs: PackageDiffTransport[]): string { | ||
return "\n" + JSON.stringify(packageDiffs, null, 2); | ||
} | ||
} | ||
|
||
export const diffService = new DiffService(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,171 @@ | ||
import {PackageManifestTransport} from "../../src/interfaces/package-export-transport"; | ||
import {ConfigUtils} from "../utls/config-utils"; | ||
import * as path from "path"; | ||
import {stringify} from "../../src/util/yaml"; | ||
import {mockCreateReadStream, mockExistsSync, mockReadFileSync} from "../utls/fs-mock-utils"; | ||
import { | ||
PackageDiffTransport | ||
} from "../../src/interfaces/diff-package.transport"; | ||
import {mockAxiosPost} from "../utls/http-requests-mock"; | ||
import {ConfigCommand} from "../../src/commands/config.command"; | ||
import { mockWriteFileSync, mockWriteSync, testTransport } from "../jest.setup"; | ||
import { FileService } from "../../src/services/file-service"; | ||
|
||
describe("Config diff", () => { | ||
|
||
beforeEach(() => { | ||
mockExistsSync(); | ||
}); | ||
|
||
it("Should show on terminal if packages have changes with hasChanges set to true and jsonResponse false", async () => { | ||
const manifest: PackageManifestTransport[] = []; | ||
manifest.push(ConfigUtils.buildManifestForKeyAndFlavor("package-key", "STUDIO")); | ||
|
||
const firstPackageNode = ConfigUtils.buildPackageNode("package-key", stringify({metadata: {description: "test"}, variables: [], dependencies: []})); | ||
const firstChildNode = ConfigUtils.buildChildNode("key-1", "package-key", "TEST"); | ||
const firstPackageZip = ConfigUtils.buildExportPackageZip(firstPackageNode, [firstChildNode], "1.0.0"); | ||
const exportedPackagesZip = ConfigUtils.buildBatchExportZip(manifest, [firstPackageZip]); | ||
|
||
mockReadFileSync(exportedPackagesZip.toBuffer()); | ||
mockCreateReadStream(exportedPackagesZip.toBuffer()); | ||
|
||
const diffResponse: PackageDiffTransport[] = [{ | ||
packageKey: "package-key", | ||
hasChanges: true, | ||
packageChanges: [], | ||
nodesWithChanges: [] | ||
}]; | ||
|
||
mockAxiosPost("https://myTeam.celonis.cloud/package-manager/api/core/packages/diff/configuration/has-changes", diffResponse); | ||
|
||
await new ConfigCommand().diffPackages("./packages.zip", true, false); | ||
|
||
expect(testTransport.logMessages.length).toBe(1); | ||
expect(testTransport.logMessages[0].message).toContain( | ||
JSON.stringify(diffResponse, null, 2) | ||
); | ||
}); | ||
|
||
it("Should show diff on terminal with hasChanges set to false and jsonResponse false", async () => { | ||
const manifest: PackageManifestTransport[] = []; | ||
manifest.push(ConfigUtils.buildManifestForKeyAndFlavor("package-key", "STUDIO")); | ||
|
||
const firstPackageNode = ConfigUtils.buildPackageNode("package-key", stringify({metadata: {description: "test"}, variables: [], dependencies: []})); | ||
const firstChildNode = ConfigUtils.buildChildNode("key-1", "package-key", "TEST"); | ||
const firstPackageZip = ConfigUtils.buildExportPackageZip(firstPackageNode, [firstChildNode], "1.0.0"); | ||
const exportedPackagesZip = ConfigUtils.buildBatchExportZip(manifest, [firstPackageZip]); | ||
|
||
mockReadFileSync(exportedPackagesZip.toBuffer()); | ||
mockCreateReadStream(exportedPackagesZip.toBuffer()); | ||
|
||
const diffResponse: PackageDiffTransport[] = [{ | ||
packageKey: "package-key", | ||
hasChanges: true, | ||
packageChanges: [ | ||
{ | ||
op: "add", | ||
path: "/test", | ||
from: "bbbb", | ||
value: JSON.parse("123") | ||
}], | ||
nodesWithChanges: [{ | ||
nodeKey: "key-1", | ||
changes: [{ | ||
op: "add", | ||
path: "/test", | ||
from: "bbb", | ||
value: JSON.parse("234") | ||
}] | ||
}] | ||
}]; | ||
|
||
mockAxiosPost("https://myTeam.celonis.cloud/package-manager/api/core/packages/diff/configuration", diffResponse); | ||
|
||
await new ConfigCommand().diffPackages("./packages.zip", false, false); | ||
|
||
expect(testTransport.logMessages.length).toBe(1); | ||
expect(testTransport.logMessages[0].message).toContain( | ||
JSON.stringify(diffResponse, null, 2) | ||
); | ||
}); | ||
|
||
it("Should generate a json file with diff info when hasChanges is set to false and jsonResponse is set to true", async () => { | ||
const manifest: PackageManifestTransport[] = []; | ||
manifest.push(ConfigUtils.buildManifestForKeyAndFlavor("package-key", "STUDIO")); | ||
|
||
const firstPackageNode = ConfigUtils.buildPackageNode("package-key", stringify({metadata: {description: "test"}, variables: [], dependencies: []})); | ||
const firstChildNode = ConfigUtils.buildChildNode("key-1", "package-key", "TEST"); | ||
const firstPackageZip = ConfigUtils.buildExportPackageZip(firstPackageNode, [firstChildNode], "1.0.0"); | ||
const exportedPackagesZip = ConfigUtils.buildBatchExportZip(manifest, [firstPackageZip]); | ||
|
||
mockReadFileSync(exportedPackagesZip.toBuffer()); | ||
mockCreateReadStream(exportedPackagesZip.toBuffer()); | ||
|
||
const diffResponse: PackageDiffTransport[] = [{ | ||
packageKey: "package-key", | ||
hasChanges: true, | ||
packageChanges: [ | ||
{ | ||
op: "add", | ||
path: "/test", | ||
from: "bbbb", | ||
value: JSON.parse("123") | ||
}], | ||
nodesWithChanges: [{ | ||
nodeKey: "key-1", | ||
changes: [{ | ||
op: "add", | ||
path: "/test", | ||
from: "bbb", | ||
value: JSON.parse("234") | ||
}] | ||
}] | ||
}]; | ||
|
||
mockAxiosPost("https://myTeam.celonis.cloud/package-manager/api/core/packages/diff/configuration", diffResponse); | ||
|
||
await new ConfigCommand().diffPackages("./packages.zip", false, true); | ||
|
||
const expectedFileName = testTransport.logMessages[0].message.split(FileService.fileDownloadedMessage)[1]; | ||
|
||
expect(mockWriteFileSync).toHaveBeenCalledWith(path.resolve(process.cwd(), expectedFileName), expect.any(String), {encoding: "utf-8"}); | ||
const exportedPackageDiffTransport = JSON.parse(mockWriteFileSync.mock.calls[0][1]) as PackageDiffTransport[]; | ||
expect(exportedPackageDiffTransport.length).toBe(1); | ||
|
||
const exportedFirstPackageDiffTransport = exportedPackageDiffTransport.filter(diffTransport => diffTransport.packageKey === firstPackageNode.key); | ||
expect(exportedFirstPackageDiffTransport).toEqual(diffResponse); | ||
}); | ||
|
||
it("Should generate a json file with info whether packages have changes when hasChanges is set to true and jsonResponse is set to true", async () => { | ||
const manifest: PackageManifestTransport[] = []; | ||
manifest.push(ConfigUtils.buildManifestForKeyAndFlavor("package-key", "STUDIO")); | ||
|
||
const firstPackageNode = ConfigUtils.buildPackageNode("package-key", stringify({metadata: {description: "test"}, variables: [], dependencies: []})); | ||
const firstChildNode = ConfigUtils.buildChildNode("key-1", "package-key", "TEST"); | ||
const firstPackageZip = ConfigUtils.buildExportPackageZip(firstPackageNode, [firstChildNode], "1.0.0"); | ||
const exportedPackagesZip = ConfigUtils.buildBatchExportZip(manifest, [firstPackageZip]); | ||
|
||
mockReadFileSync(exportedPackagesZip.toBuffer()); | ||
mockCreateReadStream(exportedPackagesZip.toBuffer()); | ||
|
||
const diffResponse: PackageDiffTransport[] = [{ | ||
packageKey: "package-key", | ||
hasChanges: true, | ||
packageChanges: [], | ||
nodesWithChanges: [] | ||
}]; | ||
|
||
mockAxiosPost("https://myTeam.celonis.cloud/package-manager/api/core/packages/diff/configuration/has-changes", diffResponse); | ||
|
||
await new ConfigCommand().diffPackages("./packages.zip", true, true); | ||
|
||
const expectedFileName = testTransport.logMessages[0].message.split(FileService.fileDownloadedMessage)[1]; | ||
|
||
expect(mockWriteFileSync).toHaveBeenCalledWith(path.resolve(process.cwd(), expectedFileName), expect.any(String), {encoding: "utf-8"}); | ||
const exportedPackageDiffTransport = JSON.parse(mockWriteFileSync.mock.calls[0][1]) as PackageDiffTransport[]; | ||
expect(exportedPackageDiffTransport.length).toBe(1); | ||
|
||
const exportedFirstPackageDiffTransport = exportedPackageDiffTransport.filter(diffTransport => diffTransport.packageKey === firstPackageNode.key); | ||
expect(exportedFirstPackageDiffTransport).toEqual(diffResponse); | ||
}); | ||
}); |