Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#44] Branches Comparison #45

Merged
merged 21 commits into from
Nov 18, 2022
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .ci/actions/generate-data/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ inputs:
description: "the gh-pages branch"
default: "gh-pages"
required: false
branches:
description: "A comma separated list of branches to compare. Like `main,8.30.x,8.29.x`"
required: false

runs:
using: "composite"
Expand All @@ -62,6 +65,7 @@ runs:
created-by: ${{ inputs.created-by }}
created-url: ${{ inputs.created-url }}
logger-level: ${{ inputs.logger-level }}
branches: ${{ inputs.branches }}
env:
GITHUB_TOKEN: ${{ inputs.github-token }}
- name: Commit & Push changes
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ Here the main important steps performed by **generate-data** action:
| created-url | false | | Normally the job generating the info URL |
| logger-level | false | info | The log level. 'info' (default) \| 'trace' \| 'debug' |
| gh-pages-branch | false | gh-pages | The branch used by `gh-pages` tool, where the webpage will be stored |
| branches | false | [] | The list of branches for which to provide branches comparison |

## Usage

Expand Down
3 changes: 3 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ inputs:
description: "the log level. 'info' (default) | 'trace' | 'debug'"
default: "info"
required: false
branches:
description: "A comma separated list of branches to compare. Like `main,8.30.x,8.29.x`"
required: false
runs:
using: "node16"
main: "packages/action/dist/index.js"
Expand Down
29 changes: 15 additions & 14 deletions packages/action/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Generate Data JS Tool
# Generate Data JS Tool

This package provides a NodeJS CLI tool which basically consumes information from Github API and/or Jenkins API and generates a JSON file which is retrieved by the [React web application](https://github.com/kiegroup/chain-status/tree/main/packages/webpage/README.md).

Expand All @@ -11,6 +11,7 @@ This tool can be easy use as a NodeJS CLI tool or as a Github Action
In order to use you just need to install all required libraries, build the project and run the automatically generated distribution file at `packages/action/dist/index.js`.

1. Install libraries [run it from the project's root]

```bash
$ yarn
```
Expand All @@ -21,19 +22,19 @@ $ yarn

In this section you can find overall list of inputs that you can or must provide to the tool, either using cli or using the Github workflow.

| Field | Required | Default | Description |
|--------------------|----------|---------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| github-token | true | | The Github token that must be used to interact with Github API |
| Field | Required | Default | Description |
| ------------------ | -------- | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| github-token | true | | The Github token that must be used to interact with Github API |
| definition-file | true | | The file containing all projects for which you want to provide the status, an [example](https://raw.githubusercontent.com/kiegroup/droolsjbpm-build-bootstrap/main/.ci/pull-request-config.yaml) - more infos [here](https://github.com/kiegroup/build-chain-configuration-reader) |
| title | false | Project status | The project/webapp title |
| subtitle | false | Contribution status | The project/webapp subtitle |
| base-branch-filter | false | | A comma separated list of base branches RegEx to be filtered. Like `main,7.59.x,8.x` or `main,^7.*` |
| project-filter | false | | A comma separated list of project RegEx to be filtered. Like `drools,opta.*` or `jbpm,^drools.*` |
| created-by | false | github action | The user/machine/whatever that regenerates the report |
| created-url | false | | Normally the job generating the info URL |
| logger-level | false | info | The log level. 'info' (default) \| 'trace' \| 'debug' |
| gh-pages-branch | false | gh-pages | The branch used by `gh-pages` tool, where the webpage will be stored |

| title | false | Project status | The project/webapp title |
| subtitle | false | Contribution status | The project/webapp subtitle |
| base-branch-filter | false | | A comma separated list of base branches RegEx to be filtered. Like `main,7.59.x,8.x` or `main,^7.*` |
| project-filter | false | | A comma separated list of project RegEx to be filtered. Like `drools,opta.*` or `jbpm,^drools.*` |
| created-by | false | github action | The user/machine/whatever that regenerates the report |
| created-url | false | | Normally the job generating the info URL |
| logger-level | false | info | The log level. 'info' (default) \| 'trace' \| 'debug' |
| gh-pages-branch | false | gh-pages | The branch used by `gh-pages` tool, where the webpage will be stored |
| branches | false | [] | The list of branches for which to provide branches comparison |

### Local Execution

Expand All @@ -53,4 +54,4 @@ Here the main important steps performed by **generate-data** action:

1. Checkout in the branch where you want to store the webpage code and content, the default is `gh-pages`.
2. Execute the [chain-status](https://github.com/kiegroup/chain-status/tree/main/packages/action/dist/index.js) tool that, given a set of inputs, compute the configuration files and all the contents that are used by the webpage - this execution is performed using another [Github action](https://github.com/kiegroup/chain-status/blob/main/action.yml).
3. Commit and push the newly generated data in the target branch (e.g., `gh-pages`).
3. Commit and push the newly generated data in the target branch (e.g., `gh-pages`).
2 changes: 1 addition & 1 deletion packages/action/dist/index.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion packages/action/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@kie/chain-status-action",
"version": "0.0.4",
"version": "0.0.5",
"description": "Generates data for chain status webpage",
"repository": {
"type": "git",
Expand Down
7 changes: 6 additions & 1 deletion packages/action/src/bin/arguments.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,12 @@ function getArgumentsObject() {
)
.option(
"--projectFilter <project...>",
"a list of RegEx to filter project names",
"A list of RegEx to filter project names",
[]
)
.option(
"-b, --branches <branch...>",
"The list of branches for which you want to provide comparison",
[]
)
.parse();
Expand Down
5 changes: 4 additions & 1 deletion packages/action/src/bin/github-action.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ const start = async () => {
title: core.getInput("title"),
subtitle: core.getInput("subtitle"),
createdBy: core.getInput("created-by"),
createdUrl: core.getInput("created-url")
createdUrl: core.getInput("created-url"),
branches: core.getInput("branches")
? core.getInput("branches").split(",")
: []
};
await main(args);
};
Expand Down
54 changes: 53 additions & 1 deletion packages/action/src/lib/git-service.js
Original file line number Diff line number Diff line change
Expand Up @@ -173,11 +173,63 @@ const listBranches = async (
}
};

const compareBranches = async (
project,
baseBranch,
headBranch,
octokit,
options = { page: 1, per_page: 100 }
) => {
const basehead = baseBranch + "..." + headBranch;
logger.info(
`Comparing branches ${baseBranch} and ${headBranch} for ${project}. https://api.github.com/repos/${project}/compare/${basehead}`
);

try {
const result = [];
const { status, data } = await octokit.repos.compareCommitsWithBasehead({
...getOwnerProject(project),
...options,
basehead
});

if (status === 200 && data && data.files.length > 0) {
result.push.apply(result, data.files);
if (data.length === options.per_page) {
result.push.apply(
result,
await compareBranches(project, baseBranch, headBranch, octokit, {
...options,
page: ++options.page
})
);
}
}
return result;
} catch (e) {
if (e.status == 404) {
logger.warn(
`Branch not found for ${project}. https://api.github.com/repos/${project}/compare/${basehead}`
);
// DO NOT BREAK - return undefined
return undefined;
}

logger.error(
`Error requesting branches comparison for ${project}. https://api.github.com/repos/${project}/compare/${basehead}`,
e
);

throw e;
}
};

module.exports = {
getDefaultBranch,
getRepository,
getPullRequests,
getChecks,
getRefStatuses,
listBranches
listBranches,
compareBranches
};
77 changes: 69 additions & 8 deletions packages/action/src/lib/github/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ const {
getChecks,
getRepository,
getRefStatuses,
listBranches
listBranches,
compareBranches
} = require("../git-service");
const { ClientError } = require("../common");
const { filterPullRequests } = require("../../utils/pullrequest-utils");
Expand Down Expand Up @@ -62,7 +63,7 @@ const loadChecks = async (node, sha, octokit) => {
};

const mapPullRequest = async (node, pullRequest, octokit) => {
return await {
return {
number: pullRequest.number,
title: pullRequest.title,
url: pullRequest.url,
Expand Down Expand Up @@ -90,11 +91,64 @@ const mapPullRequest = async (node, pullRequest, octokit) => {
};
};

const mapPullRequestInfo = async (node, pullRequests, octokit) => {
const mapFileDiff = file => {
return {
sha: file.sha
};
};
lampajr marked this conversation as resolved.
Show resolved Hide resolved

const mapBranchComparison = async (
project,
baseBranch,
headBranches,
octokit
) => {
const diffsByBranch = Object.fromEntries(
await Promise.all(
headBranches.map(async b => [
b,
(
await compareBranches(project, baseBranch, b, octokit)
)?.map(mapFileDiff)
])
)
);

// [b1, {b2: [files..], b3: [files..]]
return [baseBranch, diffsByBranch];
};

const mapProjectBranchesComparison = async (
project,
branchesToCompare,
octokit
) => {
return Object.fromEntries(
await Promise.all(
(branchesToCompare ?? []).map(
async branch =>
await mapBranchComparison(
project,
branch,
branchesToCompare.filter(br => br !== branch),
octokit
)
)
)
);
};

const mapProjectInfo = async (
node,
pullRequests,
branchesToCompare,
octokit
) => {
const baseRepo =
pullRequests && pullRequests.length
? pullRequests[0].base.repo
: await getRepository(node.project, octokit);

return {
key: node.project,
name: baseRepo.name,
Expand All @@ -108,6 +162,11 @@ const mapPullRequestInfo = async (node, pullRequests, octokit) => {
pulls_url: baseRepo.pulls_url,
pullRequests: await Promise.all(
pullRequests.map(async e => await mapPullRequest(node, e, octokit))
),
branchesComparison: await mapProjectBranchesComparison(
node.project,
branchesToCompare,
octokit
)
};
};
Expand Down Expand Up @@ -169,10 +228,10 @@ async function main(args, outputFolderPath, metadata, skipZero, isDebug) {

logger.info(`Filtered projects [${filteredList.map(e => e.project)}]`);

const pullRequestInformation = await Promise.all(
const projectsInformation = await Promise.all(
filteredList.map(async node => {
try {
return await mapPullRequestInfo(
return await mapProjectInfo(
node,
filterPullRequests(
filteredList[0],
Expand All @@ -188,6 +247,7 @@ async function main(args, outputFolderPath, metadata, skipZero, isDebug) {
args.baseBranchFilter
)
),
args.branches,
octokit
);
} catch (err) {
Expand All @@ -200,15 +260,16 @@ async function main(args, outputFolderPath, metadata, skipZero, isDebug) {
logger.error(`[${err.project}] Error checking it out. ${err.message}`);
throw err.message;
});

return saveFiles(
JSON.stringify(
{
metadata,
projects: skipZero
? pullRequestInformation.filter(
e => e.pullRequests && e.pullRequests.length > 0
? projectsInformation.filter(
p => p.pullRequests && p.pullRequests.length > 0
)
: pullRequestInformation
: projectsInformation
},
null,
isDebug ? 2 : 0
Expand Down
39 changes: 38 additions & 1 deletion packages/action/test/lib/git-service.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ const {
getPullRequests,
getChecks,
getRefStatuses,
listBranches
listBranches,
compareBranches
} = require("../../src/lib/git-service");
const { octokit } = require("../support/mock-octokit");

Expand All @@ -22,6 +23,12 @@ const mockOctokitKo = {
status: 400,
data: "error"
};
},
compareCommitsWithBasehead() {
return {
status: 400,
data: "error"
};
}
},
pulls: {
Expand Down Expand Up @@ -156,3 +163,33 @@ describe("get ref statuses", () => {
);
});
});

describe("compare branches", () => {
test("list of branches comparison received", async () => {
const files = await compareBranches(
"kiegroup/chain-status",
"base",
"head",
octokit
);
expect(files.length).toEqual(3);
const filenames = files.map(f => f.filename);
expect(filenames).toEqual(
expect.arrayContaining([
".ci/jenkins/config/branch.yaml",
".ci/jenkins/dsl/jobs.groovy",
".ci/jenkins/Jenkinsfile.prod.nightly"
])
);
});

test("empty list on ~200 status", async () => {
const files = await compareBranches(
"kiegroup/chain-status",
"base",
"head",
mockOctokitKo
);
expect(files.length).toEqual(0);
});
});
Loading