Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
83 changes: 83 additions & 0 deletions .github/skills/branch-review.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Skill: Branch Review

## Purpose
Review the current branch against `develop` and report only material issues with high signal: bugs, regressions, API breaks, resource/concurrency risks, and behavior changes.

## When to Use
- Before opening a pull request to `develop`
- After major refactoring or API changes
- When you want a strict, impact-focused review

## Review Scope (RLib-specific)
1. **Public API compatibility first**
- Treat removals/signature changes in public API as high priority by default
- If branch is intentionally alpha-breaking, mark these as accepted and continue

2. **Prioritize API surface over internals**
- Start with changed files in `src/main/java`
- Prioritize non-`impl/` packages
- Review `impl/` changes when they can affect exposed behavior

3. **Javadoc quality is part of API review**
- Check public API javadocs for:
- `@since 10.0.0`
- Active voice descriptions
- No trailing periods in `@param`/`@return`
- No unnecessary getter/setter javadocs

4. **Collections performance pattern**
- Verify empty-state fast paths (`isEmpty()`) in collection operations
- Ensure no unnecessary allocation/iteration when collections are empty

5. **Runtime/integration constraints**
- Many integration tests use Testcontainers
- If Docker is unavailable, call out that integration validation is limited

6. **Testing conventions awareness**
- Prefer AssertJ assertions
- Keep test naming and style aligned with repo conventions

7. **Version mapping correctness**
- For version-to-name lookups (for example OS distribution naming), verify runtime version normalization before map access
- Confirm behavior for real version formats (for example `10.15.7`, `14.4.1`, `15.1`) with targeted tests

8. **Path handling in file discovery**
- Ensure file discovery helpers return full/usable paths when downstream code reads files
- Flag bare filename returns that make behavior depend on current working directory

## Process

### 1. Gather branch diff
```bash
git --no-pager diff --name-only develop...HEAD
git --no-pager diff --stat develop...HEAD
git --no-pager diff develop...HEAD
```

### 2. Triage files
- Group into:
- Public API changes
- Internal behavior/refactoring
- Documentation-only changes

### 3. Review by risk
- Public API contract changes
- Behavioral logic changes
- Concurrency/resource handling
- Performance-sensitive paths
- Documentation contract gaps (for public API)

### 4. Report findings
Use this format:
- **Severity:** High / Medium / Low
- **File:** path
- **Issue:** concise technical problem
- **Impact:** why it matters in real usage
- **Fix:** concrete recommendation

Only include findings that are actionable and materially important.

## Output Expectations
- If no material issues: explicitly state no material issues found
- If issues exist: provide a short prioritized list
- Do not include style-only or trivial nits
14 changes: 2 additions & 12 deletions .github/skills/generate-branch-summary.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,6 @@ Group modifications by their nature:
Create a section in `summary.md` with this format:

```markdown
# Branch: <branch-name>

**Status:** <Ready for review / In progress / Draft>
**Commits:** <number> (e.g., "1 (abc1234 - 'commit message')" or "3 commits")
**Version:** <old-version> → <new-version> (if applicable)

## Changes Summary

### <Category 1> (e.g., "New Array API")
Expand Down Expand Up @@ -87,6 +81,8 @@ Create a section in `summary.md` with this format:
- Use bullet points for lists
- Use bold (`**`) for emphasis on key terms
- Use inline code (`` ` ` ``) for class/method names
- Do not add a `Branch:` section or heading in the summary
- Do not add `Status`, `Commits`, or `Version` metadata lines in the summary

### 6. Output Location
Always write to `summary.md` in the repository root, replacing or updating the previous summary section.
Expand All @@ -97,12 +93,6 @@ If `summary.md` already contains unrelated sections (e.g., documentation of othe
## Example Output

```markdown
# Branch: update-api-part-2

**Status:** Ready for review
**Commits:** 1 (1367d9b - "small improvements")
**Version:** 10.0.alpha13 → 10.0.alpha14

## Changes Summary

### 1. New Array API: `tryTrimTo(int)`
Expand Down
9 changes: 6 additions & 3 deletions .github/skills/generate-javadoc.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ When the user asks to:
2. **Function @return** - use "the function result" for consistency
3. **Predicate @return** - use "true if the arguments match the predicate" or "true if the arguments match the predicate, false otherwise"
4. **Supplier @return** - describe what is supplied (e.g., "the char value" not just "a result")
5. **Signature-text alignment** - ensure class-level description and type-parameter text match the exact argument order in `make(...)`/`accept(...)` methods (for example, `A, int, C` must be described as "an object, an int, and another object", while `A, B, int` must be described as "two objects and one int")

### Javadoc Standards
Each documented element must include:
Expand Down Expand Up @@ -129,6 +130,7 @@ public interface IntObjConsumer<B> {
- Remove obvious/redundant javadocs (getters, setters, constants)
- Remove duplicate `@see` references
- Add missing `@since` tags
- Fix swapped functional-interface descriptions so they match the method signature argument order

## Execution Steps

Expand All @@ -145,9 +147,10 @@ public interface IntObjConsumer<B> {
3. **Read each file** to understand existing documentation state

4. **Add Javadocs** using `replace_string_in_file` tool:
- Add class-level Javadoc with description and `@since`
- Add method-level Javadocs with description and `@since`
- Add `@param`/`@return` only for non-trivial methods
- Add class-level Javadoc with description and `@since`
- Add method-level Javadocs with description and `@since`
- Add `@param`/`@return` only for non-trivial methods
- For functional interfaces, verify description wording against the exact parameter order in method signatures

5. **Validate changes:**
```bash
Expand Down
14 changes: 7 additions & 7 deletions .github/workflows/develop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,16 @@ jobs:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6

- name: Set up JDK 21
uses: actions/setup-java@v4
uses: actions/setup-java@v5
with:
java-version: '21'
distribution: 'temurin'

- name: Setup Gradle
uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0
uses: gradle/actions/setup-gradle@v6

- name: Compile all modules
run: ./gradlew testClasses
Expand All @@ -32,7 +32,7 @@ jobs:
run: ./gradlew test

- name: Generate test report
uses: mikepenz/action-junit-report@v5
uses: mikepenz/action-junit-report@v6
if: success() || failure() # always run even if the previous step fails
with:
report_paths: '**/build/test-results/test/TEST-*.xml'
Expand Down Expand Up @@ -61,13 +61,13 @@ jobs:
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6

- name: Set up JDK 21
uses: actions/setup-java@v4
uses: actions/setup-java@v5
with:
java-version: '21'
distribution: 'temurin'

- name: Generate and submit dependency graph
uses: gradle/actions/dependency-submission@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0
uses: gradle/actions/dependency-submission@v6
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@
/**/build
/**/out
/**/.gradle
/summary.md
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ repositories {
}

ext {
rlibVersion = "10.0.alpha14"
rlibVersion = "10.0.alpha15"
}

dependencies {
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
rootProject.version = "10.0.alpha14"
rootProject.version = "10.0.alpha15"
group = 'javasabr.rlib'

allprojects {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,8 @@
import javasabr.rlib.io.impl.ReuseBytesInputStream;
import javasabr.rlib.io.impl.ReuseBytesOutputStream;
import javasabr.rlib.io.util.IoUtils;
import javasabr.rlib.logger.api.Logger;
import javasabr.rlib.logger.api.LoggerManager;
import lombok.AccessLevel;
import lombok.CustomLog;
import lombok.Getter;
import lombok.experimental.Accessors;
import lombok.experimental.FieldDefaults;
Expand All @@ -33,13 +32,12 @@
/**
* @author JavaSaBr
*/
@CustomLog
@Accessors(fluent = true)
@Getter(AccessLevel.PROTECTED)
@FieldDefaults(level = AccessLevel.PROTECTED)
public class ClassPathScannerImpl implements ClassPathScanner {

protected static final Logger LOGGER = LoggerManager.getLogger(ClassPathScanner.class);


private static final String CLASS_PATH = System.getProperty("java.class.path");
private static final String PATH_SEPARATOR = File.pathSeparator;
private static final String CLASS_EXTENSION = ".class";
Expand Down Expand Up @@ -176,10 +174,10 @@ private void loadClass(
if (!name.endsWith(CLASS_EXTENSION)) {
return;
} else if(MODULE_INFO_CLASS.equals(name)) {
LOGGER.debug("Skip loading module-info...");
log.debug("Skip loading module-info...");
return;
} else if(name.startsWith(META_INF_PREFIX)) {
LOGGER.debug("Skip loading META-INF class...");
log.debug("Skip loading META-INF class...");
return;
}

Expand All @@ -199,19 +197,19 @@ private void loadClass(
className = result.toString();

} catch (Exception e) {
LOGGER.warning(name, File.separator, "Incorrect replaced class name:[%s] to java path, used separator:[%s]"::formatted);
log.warn(name, File.separator, "Incorrect replaced class name:[%s] to java path, used separator:[%s]"::formatted);
return;
}

LOGGER.debug(className, "Try to load class:[%s]"::formatted);
log.debug(className, "Try to load class:[%s]"::formatted);
try {
container.add(loader().loadClass(className));
} catch (NoClassDefFoundError error) {
LOGGER.warning(className, name, rootPath, file,
log.warn(className, name, rootPath, file,
"Can't load class:[%s] with original name:[%s], root folder:[%s] and class file:[%s]"::formatted);
LOGGER.warning(error);
log.warn(error);
} catch (Throwable e) {
LOGGER.warning(e);
log.warn(e);
}
}

Expand All @@ -220,7 +218,7 @@ private void scanDirectory(
MutableArray<Class<?>> classes,
MutableArray<String> resources,
Path directory) {
LOGGER.debug(directory, "Scanning directory:[%s]"::formatted);
log.debug(directory, "Scanning directory:[%s]"::formatted);
try (DirectoryStream<Path> stream = Files.newDirectoryStream(directory)) {
for (Path file : stream) {

Expand Down Expand Up @@ -261,15 +259,15 @@ private void scanDirectory(
}

} catch (IOException ex) {
LOGGER.warning(ex);
log.warn(ex);
}
}

private void scanJar(MutableArray<Class<?>> classes, MutableArray<String> resources, Path jarFile) {
LOGGER.debug(jarFile, "Scanning jar:[%s]"::formatted);
log.debug(jarFile, "Scanning jar:[%s]"::formatted);

if (!Files.exists(jarFile)) {
LOGGER.warning(jarFile, "Jar file:[%s] does not exists"::formatted);
log.warn(jarFile, "Jar file:[%s] does not exists"::formatted);
return;
}

Expand All @@ -280,10 +278,10 @@ private void scanJar(MutableArray<Class<?>> classes, MutableArray<String> resour
try (var jin = new JarInputStream(Files.newInputStream(jarFile))) {
scanJarInputStream(classes, resources, rout, rin, buffer, jin);
} catch (ZipException e) {
LOGGER.warning(jarFile, "Can't open zip file:[%s]"::formatted);
LOGGER.warning(e);
log.warn(jarFile, "Can't open zip file:[%s]"::formatted);
log.warn(e);
} catch (IOException e) {
LOGGER.warning(e);
log.warn(e);
}
}

Expand Down Expand Up @@ -317,7 +315,7 @@ private void scanJarInputStream(
}

private void scanJar(MutableArray<Class<?>> classes, MutableArray<String> resources, InputStream jarFile) {
LOGGER.debug(jarFile, "Scanning jar:[%s]"::formatted);
log.debug(jarFile, "Scanning jar:[%s]"::formatted);

var rout = new ReuseBytesOutputStream();
var rin = new ReuseBytesInputStream();
Expand All @@ -326,10 +324,10 @@ private void scanJar(MutableArray<Class<?>> classes, MutableArray<String> resour
try (var jin = new JarInputStream(jarFile)) {
scanJarInputStream(classes, resources, rout, rin, buffer, jin);
} catch (final ZipException e) {
LOGGER.warning(jarFile, arg -> "Can't open zip file " + arg);
LOGGER.warning(e);
log.warn(jarFile, arg -> "Can't open zip file " + arg);
log.warn(e);
} catch (final IOException e) {
LOGGER.warning(e);
log.warn(e);
}
}

Expand All @@ -347,7 +345,7 @@ public void scan(@Nullable Predicate<String> filter) {
continue;
}

LOGGER.debug(file, "Scanning file:[%s]"::formatted);
log.debug(file, "Scanning file:[%s]"::formatted);

var filename = file
.getFileName()
Expand All @@ -363,7 +361,7 @@ public void scan(@Nullable Predicate<String> filter) {
this.classes = classes.toArray(ArrayUtils.EMPTY_CLASS_ARRAY);
this.resources = resources.toArray(ArrayUtils.EMPTY_STRING_ARRAY);

LOGGER.debug(
log.debug(
classes().length,
resources().length,
"Scanned [%s] classes and [%s] resources"::formatted);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@
import javasabr.rlib.collections.array.MutableArray;
import javasabr.rlib.common.util.Utils;
import lombok.AccessLevel;
import lombok.CustomLog;
import lombok.experimental.FieldDefaults;

/**
* @author JavaSaBr
*/
@CustomLog
@FieldDefaults(level = AccessLevel.PROTECTED, makeFinal = true)
public class ManifestClassPathScannerImpl extends ClassPathScannerImpl {

Expand Down Expand Up @@ -50,7 +52,7 @@ protected Array<String> calculateManifestClassPath() {
URL url = urls.nextElement();
InputStream is = url.openStream();
if (is == null) {
LOGGER.warning(url, arg -> "not found input stream for the url " + arg);
log.warn(url, arg -> "not found input stream for the url " + arg);
continue;
}

Expand All @@ -72,7 +74,7 @@ protected Array<String> calculateManifestClassPath() {
}

} catch (Exception exc) {
LOGGER.warning(exc);
log.warn(exc);
}
}

Expand Down
Loading
Loading