Skip to content

Commit

Permalink
fixed not changable relevancy, added case for long adf
Browse files Browse the repository at this point in the history
  • Loading branch information
Mateusz Duda committed Jul 11, 2024
1 parent 3628003 commit d27cb28
Show file tree
Hide file tree
Showing 9 changed files with 236 additions and 47 deletions.
6 changes: 6 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"command": "npm run build && npm run test",
"name": "Build & run tests",
"request": "launch",
"type": "node-terminal"
},
{
"command": "npm run build && scope --report-for-commit-list buildData.json log.html",
"name": "Run test of --report-for-commit-list",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "scope-tags",
"version": "0.3.4",
"version": "0.3.5",
"description": "Output human readable test scope report for QA",
"main": "dist/scope.js",
"types": "dist/scope.d.ts",
Expand Down
31 changes: 24 additions & 7 deletions src/Git/GitRepository.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { execSync } from "child_process";
import { Commit, Note, Oid, Repository, Revwalk, Signature } from "nodegit";
import { FileData, GitDeltaType, VerificationInfo } from "./Types";
import path from "path";
import { FileTagsDatabase, FileStatusInDatabase } from "../Scope/FileTagsDatabase";
import { RelevancyMap } from "../Relevancy/Relevancy";
import { RelevancyManager } from "../Relevancy/RelevancyManager";
import { ConfigFile } from "../Scope/ConfigFile";
import { execSync } from "child_process";
import { RelevancyMap } from "../Relevancy/Relevancy";
import { FileStatusInDatabase, FileTagsDatabase } from "../Scope/FileTagsDatabase";
import { FileData, GitDeltaType, VerificationInfo } from "./Types";

export class GitRepository {

Expand All @@ -18,6 +18,10 @@ export class GitRepository {
this._root = root;
}

public get root() {
return this._root;
}

public async getFileDataForUnpushedCommits(maxCommitCount: number = 20): Promise<FileData[]> {
const unpushedCommits = await this.getUnpushedCommits(maxCommitCount);

Expand Down Expand Up @@ -274,7 +278,11 @@ export class GitRepository {
return commitId;
}

public async amendMostRecentCommit(files: string[], newCommitMessage: string) {
public async amendMostRecentCommit(files: string[], newCommitMessage: string, useGitNatively = false) {
if(useGitNatively) {
this._amendFilesUsingNativeGitCommand(files, newCommitMessage);
return;
}

const repository = await this._getRepository();
const index = await repository.refreshIndex();
Expand Down Expand Up @@ -458,7 +466,16 @@ export class GitRepository {
}
}

public get root() {
return this._root;
/**
* Used for tests only, because nodeGit's commit.amend blocks them
*/
private _amendFilesUsingNativeGitCommand(files: string[], newCommitMessage: string) {
const normalizedCommitMessage = newCommitMessage.replace(/(\r\n|\n|\r)/gm, "");

files.forEach(file => {
execSync(`cd ${this._root} && git add ${file}`);
})

execSync(`cd ${this._root} && git commit --amend -m ${JSON.stringify(normalizedCommitMessage)}`);
}
}
36 changes: 9 additions & 27 deletions src/Relevancy/RelevancyManager.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Commit } from "nodegit";
import { FileData } from "../Git/Types";
import { CommitMessageRelevancyInfo, Relevancy, RelevancyDescriptions, RelevancyMap } from "./Relevancy";
import { FileTagsDatabase } from "../Scope/FileTagsDatabase";
import { CommitMessageRelevancyInfo, Relevancy, RelevancyDescriptions, RelevancyMap } from "./Relevancy";

const { Scale } = require('enquirer');

Expand Down Expand Up @@ -82,37 +82,19 @@ export class RelevancyManager {
} as CommitMessageRelevancyInfo;
});

// Merge relevancies - if some are duplicates, select those with higher relevancy - TODO: This should be testable -> add test
const allRelevancies: CommitMessageRelevancyInfo[] = relevancyArray.concat(relevancyArrayFromCurrentCommit);
const mergedRelevancies: CommitMessageRelevancyInfo[] = [];

relevancyArray.concat(relevancyArrayFromCurrentCommit).forEach(relevancy => {

if (mergedRelevancies.some(mergedRelevancy => mergedRelevancy.path === relevancy.path)) {
return;
}
// Merge relevancies - if some are duplicates, overwrite them
relevancyArray.forEach(relevancyEntry => {
const matchingRelevancyFromCurrentCommit = relevancyArrayFromCurrentCommit.find(relevancy => relevancy.path === relevancyEntry.path);

const relevanciesForThisFileData = allRelevancies.filter(mergedRelevancy => mergedRelevancy.path === relevancy.path);

if (relevanciesForThisFileData.length === 0) {
throw new Error("[RelevancyManager] Could not merge relevancy data to current head commit");
} else if (relevanciesForThisFileData.length === 1) {
mergedRelevancies.push(relevancy);
return;
if(matchingRelevancyFromCurrentCommit) {
matchingRelevancyFromCurrentCommit.relevancy = relevancyEntry.relevancy;
matchingRelevancyFromCurrentCommit.commit = relevancyEntry.commit;
} else {
// Find highest relevancy for this file
let highestPossibleRelevancyData = relevanciesForThisFileData[0];

for (let i = 1; i < relevanciesForThisFileData.length; i++) {
if (this._getIndexByRelevancy(relevanciesForThisFileData[i].relevancy) > this._getIndexByRelevancy(highestPossibleRelevancyData.relevancy)) {
highestPossibleRelevancyData = relevanciesForThisFileData[i];
}
}
mergedRelevancies.push(highestPossibleRelevancyData);
relevancyArrayFromCurrentCommit.push(relevancyEntry);
}
});

const outputRelevancyArray = JSON.stringify(mergedRelevancies);
const outputRelevancyArray = JSON.stringify(relevancyArray);

const commitMessageWithoutRelevancy = headCommit.message().replace(/__relevancy__.+__relevancy__/gs, "");

Expand Down
8 changes: 7 additions & 1 deletion src/Report/ADFValidator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import Ajv from "ajv";
import { Logger } from "../Logger/Logger";

export class ADFValidator {
private static SCHEMA_URL = "https://unpkg.com/@atlaskit/[email protected]/dist/json-schema/v1/full.json";
private static SCHEMA_URL = "http://go.atlassian.com/adf-json-schema";
private static JIRA_COMMENT_MAX_LENGTH = 32_767;

private _schema: unknown;

Expand Down Expand Up @@ -34,6 +35,11 @@ export class ADFValidator {

const ajv = new Ajv({ jsonPointers: true });

if(commentJSON.length > ADFValidator.JIRA_COMMENT_MAX_LENGTH) {
console.log(`[ADFValidator] Maximum length of Jira comment (${ADFValidator.JIRA_COMMENT_MAX_LENGTH}) exceeded`);
return false;
}

const data = JSON.parse(commentJSON);

const validate = ajv.compile(this._schema);
Expand Down
8 changes: 4 additions & 4 deletions src/Report/JiraBuilder.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { formatDate } from "./TimeUtils";
import { expand, table, doc, tableRow, tableHeader, p, strong, text, link, nestedExpand } from "./AdfUtils";
import { ReferencedFileInfo } from "../References/IReferenceFinder";
import { TagIdentifier } from "../Scope/FileTagsDatabase";
import { FileInfo } from "./ReportGenerator";
import { Relevancy } from "../Relevancy/Relevancy";
import { getScriptVersion } from "../scope";
import { TagIdentifier } from "../Scope/FileTagsDatabase";
import { doc, expand, link, nestedExpand, p, strong, table, tableHeader, tableRow, text } from "./AdfUtils";
import { FileInfo } from "./ReportGenerator";
import { formatDate } from "./TimeUtils";

export type TagIdentifierWithRelevancy = TagIdentifier & {
relevancy: Relevancy;
Expand Down
150 changes: 147 additions & 3 deletions test/commits/relevancy.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { RelevancyManager } from "../../src/Relevancy/RelevancyManager";
import { Commit } from "nodegit";
import { FileData, GitDeltaType } from "../../src/Git/Types";
import { CommitMessageRelevancyInfo, Relevancy } from "../../src/Relevancy/Relevancy";
import { Commit } from "nodegit";
import { RelevancyManager } from "../../src/Relevancy/RelevancyManager";
import { FileTagsDatabase } from "../../src/Scope/FileTagsDatabase";
import { TagsDefinitionFile } from "../../src/Scope/TagsDefinitionFile";
import { cloneMockRepositoryToFolder, commitModitication, makeUniqueFolderForTest } from "../utils/utils";

const fs = require('fs');

Expand Down Expand Up @@ -173,5 +176,146 @@ describe("Relevancy manager tests", () => {
checkRelevancyAndFileData(generatedRelevancyData[0], mockFileData1, mockRelevancyData.get(mockFileData1), "sha");
checkRelevancyAndFileData(generatedRelevancyData[1], mockFileData2, mockRelevancyData.get(mockFileData2), "sha");
checkRelevancyAndFileData(generatedRelevancyData[2], mockFileData3, mockRelevancyData.get(mockFileData3), "sha");
})
});

it("Correctly replaces existing relevancy in a commit message (low -> high relevancy)", async () => {
const FOLDER_PATH = makeUniqueFolderForTest();
const REPO_PATH = cloneMockRepositoryToFolder(FOLDER_PATH);

// Assume relevancy is already added

const repository = await commitModitication(
["src/tagged-file.js"],
REPO_PATH,
`[TEST - 1234] There is correct relevancy data in this commit message
__relevancy__[{"path":"src/tagged-file.js","relevancy":"LOW","commit":"__current__"}]__relevancy__
`);

const relevancyManager = new RelevancyManager();

const headCommit = (await repository.getUnpushedCommits())[0];

expect(headCommit).toBeDefined();
expect(relevancyManager.doesCommitMessageHaveRelevancyData(headCommit.message())).toBe(true);

// And user selects new relevancy using npx scope --add

const userSelectedRelevancy = new Map<FileData, Relevancy>([
[{
oldPath: "src/tagged-file.js",
newPath: "src/tagged-file.js",
change: GitDeltaType.MODIFIED,
linesAdded: 100,
linesRemoved: 200,
} as FileData,
Relevancy.HIGH]
]);

const newCommitMessage = relevancyManager.convertRelevancyDataToCommitMessage(userSelectedRelevancy, headCommit);

expect(relevancyManager.doesCommitMessageHaveRelevancyData(newCommitMessage)).toBe(true);

const extractedRelevancy = relevancyManager.convertCommitMessageToRelevancyData({
message: () => newCommitMessage,
sha: () => "sha",
} as Commit);

expect(extractedRelevancy[0]).toBeDefined();
expect(extractedRelevancy[0].path).toBe("src/tagged-file.js");
expect(extractedRelevancy[0].relevancy).toBe(Relevancy.HIGH);

const tagsDefinitionFile = new TagsDefinitionFile(REPO_PATH);
const fileTagsDatabase = new FileTagsDatabase(REPO_PATH);

await repository.amendMostRecentCommit([fileTagsDatabase.getPath(), tagsDefinitionFile.getPath()], newCommitMessage, true);

const headCommitAfterChange = (await repository.getUnpushedCommits())[0];

expect(headCommitAfterChange).toBeDefined();
const msg = headCommitAfterChange.message();

expect(relevancyManager.doesCommitMessageHaveRelevancyData(headCommitAfterChange.message())).toBe(true);


const newExtractedRelevancy = relevancyManager.convertCommitMessageToRelevancyData({
message: () => headCommitAfterChange.message(),
sha: () => "sha",
} as Commit);

expect(newExtractedRelevancy[0]).toBeDefined();
expect(newExtractedRelevancy[0].path).toBe("src/tagged-file.js");
expect(newExtractedRelevancy[0].relevancy).toBe(Relevancy.HIGH);
});


it("Correctly replaces existing relevancy in a commit message (high -> low relevancy)", async () => {
const FOLDER_PATH = makeUniqueFolderForTest();
const REPO_PATH = cloneMockRepositoryToFolder(FOLDER_PATH);

// Assume relevancy is already added

const repository = await commitModitication(
["src/tagged-file.js"],
REPO_PATH,
`[TEST - 1234] There is correct relevancy data in this commit message
__relevancy__[{"path":"src/tagged-file.js","relevancy":"HIGH","commit":"__current__"}]__relevancy__
`);

const relevancyManager = new RelevancyManager();

const headCommit = (await repository.getUnpushedCommits())[0];

expect(headCommit).toBeDefined();
expect(relevancyManager.doesCommitMessageHaveRelevancyData(headCommit.message())).toBe(true);

// And user selects new relevancy using npx scope --add

const userSelectedRelevancy = new Map<FileData, Relevancy>([
[{
oldPath: "src/tagged-file.js",
newPath: "src/tagged-file.js",
change: GitDeltaType.MODIFIED,
linesAdded: 100,
linesRemoved: 200,
} as FileData,
Relevancy.LOW]
]);

const newCommitMessage = relevancyManager.convertRelevancyDataToCommitMessage(userSelectedRelevancy, headCommit);

expect(relevancyManager.doesCommitMessageHaveRelevancyData(newCommitMessage)).toBe(true);

const extractedRelevancy = relevancyManager.convertCommitMessageToRelevancyData({
message: () => newCommitMessage,
sha: () => "sha",
} as Commit);

expect(extractedRelevancy[0]).toBeDefined();
expect(extractedRelevancy[0].path).toBe("src/tagged-file.js");
expect(extractedRelevancy[0].relevancy).toBe(Relevancy.LOW);

const tagsDefinitionFile = new TagsDefinitionFile(REPO_PATH);
const fileTagsDatabase = new FileTagsDatabase(REPO_PATH);

await repository.amendMostRecentCommit([fileTagsDatabase.getPath(), tagsDefinitionFile.getPath()], newCommitMessage, true);

const headCommitAfterChange = (await repository.getUnpushedCommits())[0];

expect(headCommitAfterChange).toBeDefined();
const msg = headCommitAfterChange.message();

expect(relevancyManager.doesCommitMessageHaveRelevancyData(headCommitAfterChange.message())).toBe(true);


const newExtractedRelevancy = relevancyManager.convertCommitMessageToRelevancyData({
message: () => headCommitAfterChange.message(),
sha: () => "sha",
} as Commit);

expect(newExtractedRelevancy[0]).toBeDefined();
expect(newExtractedRelevancy[0].path).toBe("src/tagged-file.js");
expect(newExtractedRelevancy[0].relevancy).toBe(Relevancy.LOW);
});
});
Loading

0 comments on commit d27cb28

Please sign in to comment.