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

Integrate Custom Random Matrix Generation and Merge Ubuntu and Windows Workflows #1776

Merged
merged 21 commits into from
Jun 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
5a6b185
###feature/Integrate random matrix generation and merge Ubuntu and Wi…
BereKanters Jun 11, 2024
076c136
###feature/Added feature-random-matrix-ci.patch file
BereKanters Jun 12, 2024
eed59ef
chore(deps): update codecov/codecov-action action to v4.5.0
renovate[bot] Jun 13, 2024
838adff
chore(deps): update gradle/gradle-build-action action to v3.4.0
renovate[bot] Jun 13, 2024
2f35e51
###feat/Integrate custom random matrix generation and merge Ubuntu an…
BereKanters Jun 14, 2024
0ed037d
###feat/Changed custom random matrix generation and merge Ubuntu and …
BereKanters Jun 14, 2024
011c353
chore(deps): update gradle/gradle-build-action action to v3.4.1
renovate[bot] Jun 15, 2024
28ff511
###feat/Updated custom random matrix generation
BereKanters Jun 15, 2024
cbdb137
Samples for CharSequence to contain in api infix 1543 (#1774)
BereKanters Jun 16, 2024
54bcb65
###feature/Integrate random matrix generation and merge Ubuntu and Wi…
BereKanters Jun 11, 2024
8534729
###feature/Added feature-random-matrix-ci.patch file
BereKanters Jun 12, 2024
1c6ae48
###feat/Integrate custom random matrix generation and merge Ubuntu an…
BereKanters Jun 14, 2024
3aa9bc4
- Updated the `forwardCompatibility` job to run in parallel with `dex…
BereKanters Jun 14, 2024
0f3bb2c
###feat/Updated custom random matrix generation
BereKanters Jun 15, 2024
0bedc23
###fix/Add feature extractors and test samples for SQLException
BereKanters Jun 16, 2024
9cb8e0e
Merge remote-tracking branch 'origin/feature/random-matrix-ci' into f…
BereKanters Jun 16, 2024
657d32d
###fix/Reset to earlier commit
BereKanters Jun 16, 2024
3cc3868
Merge remote-tracking branch 'origin/feature/random-matrix-ci' into f…
BereKanters Jun 16, 2024
7715148
###fix/Update matrix generation with proper name pattern
BereKanters Jun 16, 2024
ef22258
###fix/Updated matrix generation with axis for Distribtuion
BereKanters Jun 16, 2024
0fbadea
###fix/Updated matrix generation Axis name to right one
BereKanters Jun 16, 2024
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
50 changes: 0 additions & 50 deletions .github/workflows/build-windows.yml

This file was deleted.

2 changes: 1 addition & 1 deletion .github/workflows/check-generated-committed.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
distribution: 'adopt'
java-version: 11
- name: Setup Gradle
uses: gradle/gradle-build-action@v3.3.2
uses: gradle/gradle-build-action@v3.4.1
- name: check generateLogic committed
run: ./gradle/scripts/check-generateLogic-committed.sh
shell: bash
2 changes: 1 addition & 1 deletion .github/workflows/generate-readme-examples.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
distribution: 'adopt'
java-version: 11
- name: Setup Gradle
uses: gradle/gradle-build-action@v3.3.2
uses: gradle/gradle-build-action@v3.4.1

- name: Generate readme
run: ./gradlew :readme-examples:build
Expand Down
46 changes: 46 additions & 0 deletions .github/workflows/matrix.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
let { MatrixBuilder } = require('./matrix_builder');
const matrix = new MatrixBuilder();

// Add axes for the matrix
matrix.addAxis({
name: 'os',
title: x => x.replace('-latest', ''),
values: [
'ubuntu-latest',
'windows-latest'
]
});
matrix.addAxis({
robstoll marked this conversation as resolved.
Show resolved Hide resolved
name: 'java_version',
values: ['11', '17']
});
matrix.addAxis({
name: 'java_distribution',
title: x => x,
values: [
'corretto',
'liberica',
'microsoft',
'temurin',
'zulu'
]
});

// Configure the order of the fields in job name
matrix.setNamePattern(['os', 'java_version', 'java_distribution']);

// Ensure at least one windows and at least one linux job is present (macos is almost the same as linux)
matrix.generateRow({ os: 'windows-latest' });
matrix.generateRow({ os: 'ubuntu-latest' });

// Generate more rows, no duplicates would be generated
const include = matrix.generateRows(process.env.MATRIX_JOBS || 5);
if (include.length === 0) {
throw new Error('Matrix list is empty');
}
// Sort jobs by name, however, numeric parts are sorted appropriately
// For instance, 'windows 8' would come before 'windows 11'
include.sort((a, b) => a.name.localeCompare(b.name, undefined, { numeric: true }));

console.log(include);
console.log('::set-output name=matrix::' + JSON.stringify({ include }));
237 changes: 237 additions & 0 deletions .github/workflows/matrix_builder.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
// License: Apache-2.0
// Copyright Vladimir Sitnikov, 2021
// See https://github.com/vlsi/github-actions-random-matrix

class Axis {
constructor({name, title, values}) {
this.name = name;
this.title = title;
this.values = values;
// If all entries have same weight, the axis has uniform distribution
this.uniform = values.reduce((a, b) => a === (b.weight || 1) ? a : 0, values[0].weight || 1) !== 0
this.totalWeight = this.uniform ? values.length : values.reduce((a, b) => a + (b.weight || 1), 0);
}

static matches(row, filter) {
if (typeof filter === 'function') {
return filter(row);
}
if (Array.isArray(filter)) {
// e.g. row={os: 'windows'}; filter=[{os: 'linux'}, {os: 'linux'}]
return filter.find(v => Axis.matches(row, v));
}
if (typeof filter === 'object') {
// e.g. row={jdk: {name: 'openjdk', version: 8}}; filter={jdk: {version: 8}}
for (const [key, value] of Object.entries(filter)) {
if (!row.hasOwnProperty(key) || !Axis.matches(row[key], value)) {
return false;
}
}
return true;
}
return row === filter;
}

pickValue(filter) {
let values = this.values;
if (filter) {
values = values.filter(v => Axis.matches(v, filter));
}
if (values.length === 0) {
const filterStr = typeof filter === 'string' ? filter.toString() : JSON.stringify(filter);
throw Error(`No values produces for axis '${this.name}' from ${JSON.stringify(this.values)}, filter=${filterStr}`);
}
if (values.length === 1) {
return values[0];
}
if (this.uniform) {
return values[Math.floor(Math.random() * values.length)];
}
const totalWeight = !filter ? this.totalWeight : values.reduce((a, b) => a + (b.weight || 1), 0);
let weight = Math.random() * totalWeight;
for (let i = 0; i < values.length; i++) {
const value = values[i];
weight -= value.weight || 1;
if (weight <= 0) {
return value;
}
}
return values[values.length - 1];
}
}

class MatrixBuilder {
constructor() {
this.axes = [];
this.axisByName = {};
this.rows = [];
this.duplicates = {};
this.excludes = [];
this.includes = [];
this.failOnUnsatisfiableFilters = false;
// this.namePattern = []; // Initialize as an empty array
}

/**
* Specifies include filter (all the generated rows would comply with all the include filters)
* @param filter
*/
include(filter) {
this.includes.push(filter);
}

/**
* Specifies exclude filter (e.g. exclude a forbidden combination)
* @param filter
*/
exclude(filter) {
this.excludes.push(filter);
}

addAxis({name, title, values}) {
const axis = new Axis({name, title, values});
this.axes.push(axis);
this.axisByName[name] = axis;
return axis;
}

setNamePattern(names) {
this.namePattern = names;
}

/**
* Returns true if the row matches the include and exclude filters.
* @param row input row
* @returns {boolean}
*/
matches(row) {
return (this.excludes.length === 0 || !this.excludes.find(f => Axis.matches(row, f))) &&
(this.includes.length === 0 || this.includes.find(f => Axis.matches(row, f)));
}

failOnUnsatisfiableFilters(value) {
this.failOnUnsatisfiableFilters = value;
}

/**
* Adds a row that matches the given filter to the resulting matrix.
* filter values could be
* - literal values: filter={os: 'windows-latest'}
* - arrays: filter={os: ['windows-latest', 'linux-latest']}
* - functions: filter={os: x => x!='windows-latest'}
* @param filter object with keys matching axes names
* @returns {*}
*/
generateRow(filter) {
let res;
if (filter) {
// If matching row already exists, no need to generate more
res = this.rows.find(v => Axis.matches(v, filter));
if (res) {
return res;
}
}
for (let i = 0; i < 142; i++) {
res = this.axes.reduce(
(prev, next) =>
Object.assign(prev, {
[next.name]: next.pickValue(filter ? filter[next.name] : undefined)
}),
{}
);
if (!this.matches(res)) {
continue;
}
const key = JSON.stringify(res);
if (!this.duplicates.hasOwnProperty(key)) {
this.duplicates[key] = true;
res.name =
this.namePattern.map(axisName => {
let value = res[axisName];
const title = value.title;
if (typeof title != 'undefined') {
return title;
}
const computeTitle = this.axisByName[axisName].title;
return computeTitle ? computeTitle(value) : value;
}).filter(Boolean).join(", ");
this.rows.push(res);
return res;
}
}
const filterStr = typeof filter === 'string' ? filter.toString() : JSON.stringify(filter);
const msg = `Unable to generate row for ${filterStr}. Please check include and exclude filters`;
if (this.failOnUnsatisfiableFilters) {
throw Error(msg);
} else {
console.warn(msg);
}
}

generateRows(maxRows, filter) {
for (let i = 0; this.rows.length < maxRows && i < maxRows; i++) {
this.generateRow(filter);
}
return this.rows;
}

/**
* Computes the number of all the possible combinations.
* @returns {{bad: number, good: number}}
*/
summary() {
let position = -1;
let indices = [];
let values = {};
const axes = this.axes;
function resetValuesUpTo(nextPosition) {
for(let i=0; i<nextPosition; i++) {
const axis = axes[i];
values[axis.name] = axis.values[0];
indices[i] = 1; // next index
}
position = 0;
}

function nextAvailablePosition() {
let size = axes.length;
for (let i = position; i < size; i++) {
if (indices[i] < axes[i].values.length) {
return i;
}
}
return -1;
}
// The first initialization of the values
resetValuesUpTo(this.axes.length);
let good = 0;
let bad = 0;
while (true) {
if (indices[position] < this.axes[position].values.length) {
// Advance iterator at the current position if possible
const axis = this.axes[position];
values[axis.name] = axis.values[indices[position]];
indices[position]++;
} else {
// Advance the next iterator, and reset [0..nextPosition)
position++;
let nextPosition = nextAvailablePosition();
if (nextPosition === -1) {
break;
}
const axis = this.axes[nextPosition];
values[axis.name] = axis.values[indices[nextPosition]];
indices[nextPosition]++;
resetValuesUpTo(nextPosition);
}
if (this.matches(values)) {
good++;
} else {
bad++;
}
}
return {good: good, bad: bad};
}
}

module.exports = {Axis, MatrixBuilder};
Loading
Loading