From 453ae7e0f8dcfc873e5bfee1a3a8c7fd9718a4a9 Mon Sep 17 00:00:00 2001
From: sMouaad <93816869+sMouaad@users.noreply.github.com>
Date: Sat, 4 Apr 2026 18:30:49 +0200
Subject: [PATCH 01/12] feat: add NdArrayDemo entrypoint for Docker container
(demo showcase of all ndarray features)
---
.../sadisamir/ndarray/demo/NdArrayDemo.java | 167 ++++++++++++++++++
1 file changed, 167 insertions(+)
create mode 100644 src/main/java/org/sadisamir/ndarray/demo/NdArrayDemo.java
diff --git a/src/main/java/org/sadisamir/ndarray/demo/NdArrayDemo.java b/src/main/java/org/sadisamir/ndarray/demo/NdArrayDemo.java
new file mode 100644
index 0000000..cfd5a67
--- /dev/null
+++ b/src/main/java/org/sadisamir/ndarray/demo/NdArrayDemo.java
@@ -0,0 +1,167 @@
+package org.sadisamir.ndarray.demo;
+
+import org.sadisamir.ndarray.NdArray;
+
+/**
+ * Demonstrates NDArray library features.
+ * This class serves as the entrypoint for the Docker demo container.
+ */
+public class NdArrayDemo {
+
+ private static final String SEPARATOR = "─".repeat(50);
+
+ public static void main(String[] args) {
+ printBanner();
+ demo1DArrayCreation();
+ demo2DArrayCreation();
+ demoArithmeticOperations();
+ demoReshape();
+ demoLargeArrayDisplay();
+ printFooter();
+ }
+
+ private static void printBanner() {
+ System.out.println();
+ System.out.println("╔══════════════════════════════════════════════════╗");
+ System.out.println("║ NDArray Library Feature Showcase ║");
+ System.out.println("║ NumPy-inspired arrays for Java ║");
+ System.out.println("╚══════════════════════════════════════════════════╝");
+ System.out.println();
+ }
+
+ private static void demo1DArrayCreation() {
+ printSection("1D Array Creation");
+
+ System.out.println("Creating array from values: NdArray.array(new float[]{1, 2, 3, 4, 5})");
+ NdArray arr = NdArray.array(new float[]{1f, 2f, 3f, 4f, 5f});
+ System.out.println(" Result: " + arr);
+ System.out.println(" ndim: " + arr.getNdim());
+ System.out.println(" shape: " + formatShape(arr.getShape()));
+ System.out.println(" size: " + arr.getSize());
+ System.out.println();
+
+ System.out.println("Creating zeros array: NdArray.zeros(4)");
+ NdArray zeros = NdArray.zeros(4);
+ System.out.println(" Result: " + zeros);
+ System.out.println();
+
+ System.out.println("Creating range array: NdArray.arange(0, 10, 2)");
+ NdArray range = NdArray.arange(0f, 10f, 2f);
+ System.out.println(" Result: " + range);
+ System.out.println();
+ }
+
+ private static void demo2DArrayCreation() {
+ printSection("2D Array (Matrix) Creation");
+
+ System.out.println("Creating 2D array from matrix:");
+ System.out.println(" NdArray.array(new float[][]{{1, 2, 3}, {4, 5, 6}})");
+ NdArray matrix = NdArray.array(new float[][]{{1f, 2f, 3f}, {4f, 5f, 6f}});
+ System.out.println(" Result:");
+ printMatrix(matrix);
+ System.out.println(" ndim: " + matrix.getNdim());
+ System.out.println(" shape: " + formatShape(matrix.getShape()));
+ System.out.println(" size: " + matrix.getSize());
+ System.out.println();
+ }
+
+ private static void demoArithmeticOperations() {
+ printSection("Arithmetic Operations");
+
+ NdArray a = NdArray.array(new float[]{1f, 2f, 3f});
+ NdArray b = NdArray.array(new float[]{10f, 20f, 30f});
+
+ System.out.println("Array a: " + a);
+ System.out.println("Array b: " + b);
+ System.out.println();
+
+ System.out.println("Element-wise addition: a.add(b)");
+ NdArray sum = a.add(b);
+ System.out.println(" Result: " + sum);
+ System.out.println();
+
+ System.out.println("In-place addition: a.addInPlace(b)");
+ NdArray c = NdArray.array(new float[]{1f, 2f, 3f});
+ System.out.println(" Before: " + c);
+ c.addInPlace(b);
+ System.out.println(" After: " + c);
+ System.out.println();
+
+ System.out.println("2D Matrix addition:");
+ NdArray m1 = NdArray.array(new float[][]{{1f, 2f}, {3f, 4f}});
+ NdArray m2 = NdArray.array(new float[][]{{10f, 10f}, {10f, 10f}});
+ System.out.println(" Matrix 1:");
+ printMatrix(m1);
+ System.out.println(" Matrix 2:");
+ printMatrix(m2);
+ System.out.println(" Sum (m1.add(m2)):");
+ printMatrix(m1.add(m2));
+ System.out.println();
+ }
+
+ private static void demoReshape() {
+ printSection("Reshape Operations");
+
+ System.out.println("Creating 1D array: NdArray.arange(6)");
+ NdArray flat = NdArray.arange(6f);
+ System.out.println(" Result: " + flat);
+ System.out.println(" shape: " + formatShape(flat.getShape()));
+ System.out.println();
+
+ System.out.println("Reshaping to 2x3: flat.reshape(2, 3)");
+ NdArray reshaped = flat.reshape(2, 3);
+ System.out.println(" Result:");
+ printMatrix(reshaped);
+ System.out.println(" shape: " + formatShape(reshaped.getShape()));
+ System.out.println();
+
+ System.out.println("Reshaping to 3x2: flat.reshape(3, 2)");
+ NdArray reshaped2 = flat.reshape(3, 2);
+ System.out.println(" Result:");
+ printMatrix(reshaped2);
+ System.out.println(" shape: " + formatShape(reshaped2.getShape()));
+ System.out.println();
+ }
+
+ private static void demoLargeArrayDisplay() {
+ printSection("Large Array Display (Ellipsis)");
+
+ System.out.println("Creating large array: NdArray.arange(20)");
+ NdArray large = NdArray.arange(20f);
+ System.out.println(" Result: " + large);
+ System.out.println(" (Note: Large arrays use ellipsis notation)");
+ System.out.println();
+ }
+
+ private static void printSection(String title) {
+ System.out.println(SEPARATOR);
+ System.out.println("▶ " + title);
+ System.out.println(SEPARATOR);
+ System.out.println();
+ }
+
+ private static void printMatrix(NdArray matrix) {
+ String[] lines = matrix.toString().split("\n");
+ for (String line : lines) {
+ System.out.println(" " + line);
+ }
+ }
+
+ private static String formatShape(int[] shape) {
+ StringBuilder sb = new StringBuilder("(");
+ for (int i = 0; i < shape.length; i++) {
+ if (i > 0) sb.append(", ");
+ sb.append(shape[i]);
+ }
+ sb.append(")");
+ return sb.toString();
+ }
+
+ private static void printFooter() {
+ System.out.println(SEPARATOR);
+ System.out.println("✓ Demo completed successfully!");
+ System.out.println(" Repository: https://github.com/sMouaad/DevOps-Project");
+ System.out.println(SEPARATOR);
+ System.out.println();
+ }
+}
From f73e2b6a8e7cc7c18864608c45eaa90612dd842f Mon Sep 17 00:00:00 2001
From: sMouaad <93816869+sMouaad@users.noreply.github.com>
Date: Sat, 4 Apr 2026 18:33:00 +0200
Subject: [PATCH 02/12] feat: add Dockerfile for demo container
---
.dockerignore | 5 +++++
Dockerfile | 24 ++++++++++++++++++++++++
pom.xml | 13 +++++++++++++
3 files changed, 42 insertions(+)
create mode 100644 .dockerignore
create mode 100644 Dockerfile
diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..58e2046
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,5 @@
+target/
+.git/
+.github/
+.gitignore
+*.md
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..8080aa8
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,24 @@
+# Build stage: compile and package with Maven
+FROM eclipse-temurin:17-jdk-alpine AS builder
+
+WORKDIR /build
+
+# Copy source and build
+COPY src ./src
+RUN mvn package -DskipTests -q
+
+# Runtime stage: minimal JRE image
+FROM eclipse-temurin:17-jre-alpine
+
+LABEL org.opencontainers.image.title="NDArray Library Demo" \
+ org.opencontainers.image.description="NumPy-inspired array library for Java - Feature Demo" \
+ org.opencontainers.image.source="https://github.com/sMouaad/DevOps-Project" \
+ org.opencontainers.image.vendor="sadisamir"
+
+WORKDIR /app
+
+# Copy the built JAR from builder stage
+COPY --from=builder /build/target/ndarray-library-*.jar ./ndarray-demo.jar
+
+# Run the demo on container start
+ENTRYPOINT ["java", "-jar", "ndarray-demo.jar"]
diff --git a/pom.xml b/pom.xml
index 70bfefe..2c17089 100644
--- a/pom.xml
+++ b/pom.xml
@@ -46,6 +46,19 @@
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 3.4.2
+
+
+
+ org.sadisamir.ndarray.demo.NdArrayDemo
+
+
+
+
+
org.jacoco
jacoco-maven-plugin
From c1b00e534f4455531245eae0c545d74e50264ba0 Mon Sep 17 00:00:00 2001
From: sMouaad <93816869+sMouaad@users.noreply.github.com>
Date: Sat, 4 Apr 2026 18:33:10 +0200
Subject: [PATCH 03/12] fix: forgot to copy maven config for caching
---
Dockerfile | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/Dockerfile b/Dockerfile
index 8080aa8..330991b 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -3,6 +3,11 @@ FROM eclipse-temurin:17-jdk-alpine AS builder
WORKDIR /build
+# Copy Maven configuration first for layer caching
+COPY pom.xml .
+RUN apk add --no-cache maven \
+ && mvn dependency:go-offline -B
+
# Copy source and build
COPY src ./src
RUN mvn package -DskipTests -q
From a6e91f6108161eb11570c6262e6777b72d6b24b7 Mon Sep 17 00:00:00 2001
From: sMouaad <93816869+sMouaad@users.noreply.github.com>
Date: Sat, 4 Apr 2026 18:34:50 +0200
Subject: [PATCH 04/12] ci: add github action for docker build & push workflow
---
.github/workflows/docker.yml | 59 ++++++++++++++++++++++++++++++++++++
1 file changed, 59 insertions(+)
create mode 100644 .github/workflows/docker.yml
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
new file mode 100644
index 0000000..bf2bf8d
--- /dev/null
+++ b/.github/workflows/docker.yml
@@ -0,0 +1,59 @@
+name: Docker
+
+on:
+ push:
+ branches:
+ - main
+ tags:
+ - 'v*'
+ pull_request:
+ branches:
+ - main
+
+env:
+ REGISTRY: ghcr.io
+ IMAGE_NAME: ${{ github.repository }}
+
+jobs:
+ build-and-push:
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ packages: write
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+
+ - name: Log in to Container Registry
+ if: github.event_name != 'pull_request'
+ uses: docker/login-action@v3
+ with:
+ registry: ${{ env.REGISTRY }}
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Extract metadata (tags, labels)
+ id: meta
+ uses: docker/metadata-action@v5
+ with:
+ images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
+ tags: |
+ type=ref,event=branch
+ type=ref,event=pr
+ type=semver,pattern={{version}}
+ type=semver,pattern={{major}}.{{minor}}
+ type=sha,prefix=
+
+ - name: Build and push Docker image
+ uses: docker/build-push-action@v6
+ with:
+ context: .
+ push: ${{ github.event_name != 'pull_request' }}
+ tags: ${{ steps.meta.outputs.tags }}
+ labels: ${{ steps.meta.outputs.labels }}
+ cache-from: type=gha
+ cache-to: type=gha,mode=max
From a1d42fc9c3038d60ae97e91e34a3d981229fcac0 Mon Sep 17 00:00:00 2001
From: sMouaad <93816869+sMouaad@users.noreply.github.com>
Date: Sat, 4 Apr 2026 18:39:29 +0200
Subject: [PATCH 05/12] chore: improve readme to explain how to start the demo
---
README.md | 40 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 40 insertions(+)
diff --git a/README.md b/README.md
index 38f9515..cf83c37 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,7 @@
# NDArray Library (Java)

+
Small NumPy-inspired Java library for ndarray operations, developed as a DevOps team project.
@@ -87,6 +88,45 @@ Planned CI quality hardening:
- Optional minimum coverage threshold gate once pipeline is stable.
+## Docker
+
+A demo container is available that showcases all NDArray features on startup.
+
+### Quick Start (Pull and Run)
+
+```bash
+docker run --rm ghcr.io/smouaad/devops-project:main
+```
+
+### Build Locally
+
+```bash
+# Build the image
+docker build -t ndarray-demo .
+
+# Run the demo
+docker run --rm ndarray-demo
+```
+
+### Image Tags
+
+Images are published to GitHub Container Registry (`ghcr.io/smouaad/devops-project`):
+
+| Tag | Description |
+|-----|-------------|
+| `main` | Latest build from main branch |
+| `` | Semantic version (e.g., `1.0.0`, `1.0`) |
+| `` | Specific commit SHA |
+
+### CI/CD Pipeline
+
+The Docker workflow (`.github/workflows/docker.yml`):
+
+- Builds on every push to `main` and version tags (`v*`)
+- Validates builds on pull requests (no push)
+- Uses multi-stage build for minimal image size
+- Caches layers with GitHub Actions cache
+
## Current Status vs Mandatory Scope
Implemented:
From 16b87715a0b82edf26f4872b435f1f25d74f2c7c Mon Sep 17 00:00:00 2001
From: sMouaad <93816869+sMouaad@users.noreply.github.com>
Date: Sat, 4 Apr 2026 19:40:10 +0200
Subject: [PATCH 06/12] feat: should success in order to deploy docker image
---
.github/workflows/ci.yml | 13 +++++++++++++
.github/workflows/docker.yml | 26 +++++++++++++++++++++++++-
2 files changed, 38 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index ef279dd..0966500 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -16,6 +16,8 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
- name: Set up Java 17
uses: actions/setup-java@v4
@@ -27,6 +29,17 @@ jobs:
- name: Run verify (tests + coverage report)
run: mvn -B verify
+ - name: Run SonarQube analysis
+ env:
+ SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
+ SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
+ run: |
+ if [ -n "$SONAR_HOST_URL" ] && [ -n "$SONAR_TOKEN" ]; then
+ mvn -B org.sonarsource.scanner.maven:sonar-maven-plugin:sonar
+ else
+ echo "Skipping SonarQube analysis because SONAR_HOST_URL/SONAR_TOKEN are not configured."
+ fi
+
- name: Upload JaCoCo report artifacts
if: always()
uses: actions/upload-artifact@v4
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
index bf2bf8d..75aca86 100644
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -9,6 +9,12 @@ on:
pull_request:
branches:
- main
+ workflow_run:
+ workflows: ["CI"]
+ types:
+ - completed
+ branches:
+ - main
env:
REGISTRY: ghcr.io
@@ -17,6 +23,10 @@ env:
jobs:
build-and-push:
runs-on: ubuntu-latest
+ if: >
+ (github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success') ||
+ (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')) ||
+ github.event_name == 'pull_request'
permissions:
contents: read
packages: write
@@ -48,11 +58,25 @@ jobs:
type=semver,pattern={{major}}.{{minor}}
type=sha,prefix=
+ - name: Build Docker image
+ uses: docker/build-push-action@v6
+ with:
+ context: .
+ load: true
+ tags: ${{ env.IMAGE_NAME }}:test
+ cache-from: type=gha
+ cache-to: type=gha,mode=max
+
+ - name: Smoke test - verify container starts
+ run: |
+ docker run --rm ${{ env.IMAGE_NAME }}:test
+
- name: Build and push Docker image
+ if: github.event_name != 'pull_request'
uses: docker/build-push-action@v6
with:
context: .
- push: ${{ github.event_name != 'pull_request' }}
+ push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
From 5da8df2cdaf4267367d25db561562f7fda123b60 Mon Sep 17 00:00:00 2001
From: sMouaad <93816869+sMouaad@users.noreply.github.com>
Date: Sat, 4 Apr 2026 19:41:51 +0200
Subject: [PATCH 07/12] fix: github didn't like the filter syntax
---
.github/workflows/docker.yml | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
index 75aca86..1f66bdb 100644
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -63,13 +63,14 @@ jobs:
with:
context: .
load: true
- tags: ${{ env.IMAGE_NAME }}:test
+ tags: ${{ steps.meta.outputs.tags }}
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Smoke test - verify container starts
run: |
- docker run --rm ${{ env.IMAGE_NAME }}:test
+ IMAGE_TAG=$(echo "${{ steps.meta.outputs.tags }}" | head -n1)
+ docker run --rm "$IMAGE_TAG"
- name: Build and push Docker image
if: github.event_name != 'pull_request'
From 5c48d2948cf45a319bcfe4cd32d7a01223c1d2fa Mon Sep 17 00:00:00 2001
From: sMouaad <93816869+sMouaad@users.noreply.github.com>
Date: Sat, 4 Apr 2026 19:56:50 +0200
Subject: [PATCH 08/12] feat: use LOGGER instead of System.out
---
.../sadisamir/ndarray/demo/NdArrayDemo.java | 135 +++++++++---------
1 file changed, 69 insertions(+), 66 deletions(-)
diff --git a/src/main/java/org/sadisamir/ndarray/demo/NdArrayDemo.java b/src/main/java/org/sadisamir/ndarray/demo/NdArrayDemo.java
index cfd5a67..165622e 100644
--- a/src/main/java/org/sadisamir/ndarray/demo/NdArrayDemo.java
+++ b/src/main/java/org/sadisamir/ndarray/demo/NdArrayDemo.java
@@ -1,6 +1,8 @@
package org.sadisamir.ndarray.demo;
import org.sadisamir.ndarray.NdArray;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Demonstrates NDArray library features.
@@ -8,6 +10,7 @@
*/
public class NdArrayDemo {
+ private static final Logger LOGGER = LoggerFactory.getLogger(NdArrayDemo.class);
private static final String SEPARATOR = "─".repeat(50);
public static void main(String[] args) {
@@ -21,48 +24,48 @@ public static void main(String[] args) {
}
private static void printBanner() {
- System.out.println();
- System.out.println("╔══════════════════════════════════════════════════╗");
- System.out.println("║ NDArray Library Feature Showcase ║");
- System.out.println("║ NumPy-inspired arrays for Java ║");
- System.out.println("╚══════════════════════════════════════════════════╝");
- System.out.println();
+ LOGGER.info("");
+ LOGGER.info("╔══════════════════════════════════════════════════╗");
+ LOGGER.info("║ NDArray Library Feature Showcase ║");
+ LOGGER.info("║ NumPy-inspired arrays for Java ║");
+ LOGGER.info("╚══════════════════════════════════════════════════╝");
+ LOGGER.info("");
}
private static void demo1DArrayCreation() {
printSection("1D Array Creation");
- System.out.println("Creating array from values: NdArray.array(new float[]{1, 2, 3, 4, 5})");
+ LOGGER.info("Creating array from values: NdArray.array(new float[]{{1, 2, 3, 4, 5}})");
NdArray arr = NdArray.array(new float[]{1f, 2f, 3f, 4f, 5f});
- System.out.println(" Result: " + arr);
- System.out.println(" ndim: " + arr.getNdim());
- System.out.println(" shape: " + formatShape(arr.getShape()));
- System.out.println(" size: " + arr.getSize());
- System.out.println();
+ LOGGER.info(" Result: {}", arr);
+ LOGGER.info(" ndim: {}", arr.getNdim());
+ LOGGER.info(" shape: {}", formatShape(arr.getShape()));
+ LOGGER.info(" size: {}", arr.getSize());
+ LOGGER.info("");
- System.out.println("Creating zeros array: NdArray.zeros(4)");
+ LOGGER.info("Creating zeros array: NdArray.zeros(4)");
NdArray zeros = NdArray.zeros(4);
- System.out.println(" Result: " + zeros);
- System.out.println();
+ LOGGER.info(" Result: {}", zeros);
+ LOGGER.info("");
- System.out.println("Creating range array: NdArray.arange(0, 10, 2)");
+ LOGGER.info("Creating range array: NdArray.arange(0, 10, 2)");
NdArray range = NdArray.arange(0f, 10f, 2f);
- System.out.println(" Result: " + range);
- System.out.println();
+ LOGGER.info(" Result: {}", range);
+ LOGGER.info("");
}
private static void demo2DArrayCreation() {
printSection("2D Array (Matrix) Creation");
- System.out.println("Creating 2D array from matrix:");
- System.out.println(" NdArray.array(new float[][]{{1, 2, 3}, {4, 5, 6}})");
+ LOGGER.info("Creating 2D array from matrix:");
+ LOGGER.info(" NdArray.array(new float[][]{{{{1, 2, 3}}, {{4, 5, 6}}}})");
NdArray matrix = NdArray.array(new float[][]{{1f, 2f, 3f}, {4f, 5f, 6f}});
- System.out.println(" Result:");
+ LOGGER.info(" Result:");
printMatrix(matrix);
- System.out.println(" ndim: " + matrix.getNdim());
- System.out.println(" shape: " + formatShape(matrix.getShape()));
- System.out.println(" size: " + matrix.getSize());
- System.out.println();
+ LOGGER.info(" ndim: {}", matrix.getNdim());
+ LOGGER.info(" shape: {}", formatShape(matrix.getShape()));
+ LOGGER.info(" size: {}", matrix.getSize());
+ LOGGER.info("");
}
private static void demoArithmeticOperations() {
@@ -71,79 +74,79 @@ private static void demoArithmeticOperations() {
NdArray a = NdArray.array(new float[]{1f, 2f, 3f});
NdArray b = NdArray.array(new float[]{10f, 20f, 30f});
- System.out.println("Array a: " + a);
- System.out.println("Array b: " + b);
- System.out.println();
+ LOGGER.info("Array a: {}", a);
+ LOGGER.info("Array b: {}", b);
+ LOGGER.info("");
- System.out.println("Element-wise addition: a.add(b)");
+ LOGGER.info("Element-wise addition: a.add(b)");
NdArray sum = a.add(b);
- System.out.println(" Result: " + sum);
- System.out.println();
+ LOGGER.info(" Result: {}", sum);
+ LOGGER.info("");
- System.out.println("In-place addition: a.addInPlace(b)");
+ LOGGER.info("In-place addition: a.addInPlace(b)");
NdArray c = NdArray.array(new float[]{1f, 2f, 3f});
- System.out.println(" Before: " + c);
+ LOGGER.info(" Before: {}", c);
c.addInPlace(b);
- System.out.println(" After: " + c);
- System.out.println();
+ LOGGER.info(" After: {}", c);
+ LOGGER.info("");
- System.out.println("2D Matrix addition:");
+ LOGGER.info("2D Matrix addition:");
NdArray m1 = NdArray.array(new float[][]{{1f, 2f}, {3f, 4f}});
NdArray m2 = NdArray.array(new float[][]{{10f, 10f}, {10f, 10f}});
- System.out.println(" Matrix 1:");
+ LOGGER.info(" Matrix 1:");
printMatrix(m1);
- System.out.println(" Matrix 2:");
+ LOGGER.info(" Matrix 2:");
printMatrix(m2);
- System.out.println(" Sum (m1.add(m2)):");
+ LOGGER.info(" Sum (m1.add(m2)):");
printMatrix(m1.add(m2));
- System.out.println();
+ LOGGER.info("");
}
private static void demoReshape() {
printSection("Reshape Operations");
- System.out.println("Creating 1D array: NdArray.arange(6)");
+ LOGGER.info("Creating 1D array: NdArray.arange(6)");
NdArray flat = NdArray.arange(6f);
- System.out.println(" Result: " + flat);
- System.out.println(" shape: " + formatShape(flat.getShape()));
- System.out.println();
+ LOGGER.info(" Result: {}", flat);
+ LOGGER.info(" shape: {}", formatShape(flat.getShape()));
+ LOGGER.info("");
- System.out.println("Reshaping to 2x3: flat.reshape(2, 3)");
+ LOGGER.info("Reshaping to 2x3: flat.reshape(2, 3)");
NdArray reshaped = flat.reshape(2, 3);
- System.out.println(" Result:");
+ LOGGER.info(" Result:");
printMatrix(reshaped);
- System.out.println(" shape: " + formatShape(reshaped.getShape()));
- System.out.println();
+ LOGGER.info(" shape: {}", formatShape(reshaped.getShape()));
+ LOGGER.info("");
- System.out.println("Reshaping to 3x2: flat.reshape(3, 2)");
+ LOGGER.info("Reshaping to 3x2: flat.reshape(3, 2)");
NdArray reshaped2 = flat.reshape(3, 2);
- System.out.println(" Result:");
+ LOGGER.info(" Result:");
printMatrix(reshaped2);
- System.out.println(" shape: " + formatShape(reshaped2.getShape()));
- System.out.println();
+ LOGGER.info(" shape: {}", formatShape(reshaped2.getShape()));
+ LOGGER.info("");
}
private static void demoLargeArrayDisplay() {
printSection("Large Array Display (Ellipsis)");
- System.out.println("Creating large array: NdArray.arange(20)");
+ LOGGER.info("Creating large array: NdArray.arange(20)");
NdArray large = NdArray.arange(20f);
- System.out.println(" Result: " + large);
- System.out.println(" (Note: Large arrays use ellipsis notation)");
- System.out.println();
+ LOGGER.info(" Result: {}", large);
+ LOGGER.info(" (Note: Large arrays use ellipsis notation)");
+ LOGGER.info("");
}
private static void printSection(String title) {
- System.out.println(SEPARATOR);
- System.out.println("▶ " + title);
- System.out.println(SEPARATOR);
- System.out.println();
+ LOGGER.info(SEPARATOR);
+ LOGGER.info("▶ {}", title);
+ LOGGER.info(SEPARATOR);
+ LOGGER.info("");
}
private static void printMatrix(NdArray matrix) {
String[] lines = matrix.toString().split("\n");
for (String line : lines) {
- System.out.println(" " + line);
+ LOGGER.info(" {}", line);
}
}
@@ -158,10 +161,10 @@ private static String formatShape(int[] shape) {
}
private static void printFooter() {
- System.out.println(SEPARATOR);
- System.out.println("✓ Demo completed successfully!");
- System.out.println(" Repository: https://github.com/sMouaad/DevOps-Project");
- System.out.println(SEPARATOR);
- System.out.println();
+ LOGGER.info(SEPARATOR);
+ LOGGER.info("✓ Demo completed successfully!");
+ LOGGER.info(" Repository: https://github.com/sMouaad/DevOps-Project");
+ LOGGER.info(SEPARATOR);
+ LOGGER.info("");
}
}
From 998029d48284672ac448f7f9cd2296ba12bf26be Mon Sep 17 00:00:00 2001
From: sMouaad <93816869+sMouaad@users.noreply.github.com>
Date: Sat, 4 Apr 2026 19:56:58 +0200
Subject: [PATCH 09/12] chore: add logger dependency (slf4j
---
pom.xml | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/pom.xml b/pom.xml
index 4f7b13b..ea519d5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -22,6 +22,16 @@
+
+ org.slf4j
+ slf4j-api
+ 2.0.13
+
+
+ org.slf4j
+ slf4j-simple
+ 2.0.13
+
org.junit.jupiter
junit-jupiter
From 2afad118ba029a6c433c02e4930c5719b7001ce0 Mon Sep 17 00:00:00 2001
From: sMouaad <93816869+sMouaad@users.noreply.github.com>
Date: Sat, 4 Apr 2026 20:02:29 +0200
Subject: [PATCH 10/12] fix: changes asked by sonarqube are made - Added
constants: RESULT_FORMAT, RESULT_LABEL, SHAPE_FORMAT - Added logShape()
helper with conditional logging check - Added isInfoEnabled() guard in
printMatrix() for conditional method invocation
---
.../sadisamir/ndarray/demo/NdArrayDemo.java | 45 ++++++++++++-------
1 file changed, 28 insertions(+), 17 deletions(-)
diff --git a/src/main/java/org/sadisamir/ndarray/demo/NdArrayDemo.java b/src/main/java/org/sadisamir/ndarray/demo/NdArrayDemo.java
index 165622e..0f347cc 100644
--- a/src/main/java/org/sadisamir/ndarray/demo/NdArrayDemo.java
+++ b/src/main/java/org/sadisamir/ndarray/demo/NdArrayDemo.java
@@ -12,6 +12,9 @@ public class NdArrayDemo {
private static final Logger LOGGER = LoggerFactory.getLogger(NdArrayDemo.class);
private static final String SEPARATOR = "─".repeat(50);
+ private static final String RESULT_FORMAT = " Result: {}";
+ private static final String RESULT_LABEL = " Result:";
+ private static final String SHAPE_FORMAT = " shape: {}";
public static void main(String[] args) {
printBanner();
@@ -37,20 +40,20 @@ private static void demo1DArrayCreation() {
LOGGER.info("Creating array from values: NdArray.array(new float[]{{1, 2, 3, 4, 5}})");
NdArray arr = NdArray.array(new float[]{1f, 2f, 3f, 4f, 5f});
- LOGGER.info(" Result: {}", arr);
+ LOGGER.info(RESULT_FORMAT, arr);
LOGGER.info(" ndim: {}", arr.getNdim());
- LOGGER.info(" shape: {}", formatShape(arr.getShape()));
+ logShape(arr.getShape());
LOGGER.info(" size: {}", arr.getSize());
LOGGER.info("");
LOGGER.info("Creating zeros array: NdArray.zeros(4)");
NdArray zeros = NdArray.zeros(4);
- LOGGER.info(" Result: {}", zeros);
+ LOGGER.info(RESULT_FORMAT, zeros);
LOGGER.info("");
LOGGER.info("Creating range array: NdArray.arange(0, 10, 2)");
NdArray range = NdArray.arange(0f, 10f, 2f);
- LOGGER.info(" Result: {}", range);
+ LOGGER.info(RESULT_FORMAT, range);
LOGGER.info("");
}
@@ -60,10 +63,10 @@ private static void demo2DArrayCreation() {
LOGGER.info("Creating 2D array from matrix:");
LOGGER.info(" NdArray.array(new float[][]{{{{1, 2, 3}}, {{4, 5, 6}}}})");
NdArray matrix = NdArray.array(new float[][]{{1f, 2f, 3f}, {4f, 5f, 6f}});
- LOGGER.info(" Result:");
+ LOGGER.info(RESULT_LABEL);
printMatrix(matrix);
LOGGER.info(" ndim: {}", matrix.getNdim());
- LOGGER.info(" shape: {}", formatShape(matrix.getShape()));
+ logShape(matrix.getShape());
LOGGER.info(" size: {}", matrix.getSize());
LOGGER.info("");
}
@@ -80,7 +83,7 @@ private static void demoArithmeticOperations() {
LOGGER.info("Element-wise addition: a.add(b)");
NdArray sum = a.add(b);
- LOGGER.info(" Result: {}", sum);
+ LOGGER.info(RESULT_FORMAT, sum);
LOGGER.info("");
LOGGER.info("In-place addition: a.addInPlace(b)");
@@ -107,22 +110,22 @@ private static void demoReshape() {
LOGGER.info("Creating 1D array: NdArray.arange(6)");
NdArray flat = NdArray.arange(6f);
- LOGGER.info(" Result: {}", flat);
- LOGGER.info(" shape: {}", formatShape(flat.getShape()));
+ LOGGER.info(RESULT_FORMAT, flat);
+ logShape(flat.getShape());
LOGGER.info("");
LOGGER.info("Reshaping to 2x3: flat.reshape(2, 3)");
NdArray reshaped = flat.reshape(2, 3);
- LOGGER.info(" Result:");
+ LOGGER.info(RESULT_LABEL);
printMatrix(reshaped);
- LOGGER.info(" shape: {}", formatShape(reshaped.getShape()));
+ logShape(reshaped.getShape());
LOGGER.info("");
LOGGER.info("Reshaping to 3x2: flat.reshape(3, 2)");
NdArray reshaped2 = flat.reshape(3, 2);
- LOGGER.info(" Result:");
+ LOGGER.info(RESULT_LABEL);
printMatrix(reshaped2);
- LOGGER.info(" shape: {}", formatShape(reshaped2.getShape()));
+ logShape(reshaped2.getShape());
LOGGER.info("");
}
@@ -131,7 +134,7 @@ private static void demoLargeArrayDisplay() {
LOGGER.info("Creating large array: NdArray.arange(20)");
NdArray large = NdArray.arange(20f);
- LOGGER.info(" Result: {}", large);
+ LOGGER.info(RESULT_FORMAT, large);
LOGGER.info(" (Note: Large arrays use ellipsis notation)");
LOGGER.info("");
}
@@ -144,9 +147,17 @@ private static void printSection(String title) {
}
private static void printMatrix(NdArray matrix) {
- String[] lines = matrix.toString().split("\n");
- for (String line : lines) {
- LOGGER.info(" {}", line);
+ if (LOGGER.isInfoEnabled()) {
+ String[] lines = matrix.toString().split("\n");
+ for (String line : lines) {
+ LOGGER.info(" {}", line);
+ }
+ }
+ }
+
+ private static void logShape(int[] shape) {
+ if (LOGGER.isInfoEnabled()) {
+ LOGGER.info(SHAPE_FORMAT, formatShape(shape));
}
}
From a1803117b5be57565296df14ab8640d936117808 Mon Sep 17 00:00:00 2001
From: sMouaad <93816869+sMouaad@users.noreply.github.com>
Date: Sat, 4 Apr 2026 20:09:10 +0200
Subject: [PATCH 11/12] test: add test to ensure demo execution completes
without errors (and shush sonarqube)
---
.../sadisamir/ndarray/demo/NdArrayDemoTest.java | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
create mode 100644 src/test/java/org/sadisamir/ndarray/demo/NdArrayDemoTest.java
diff --git a/src/test/java/org/sadisamir/ndarray/demo/NdArrayDemoTest.java b/src/test/java/org/sadisamir/ndarray/demo/NdArrayDemoTest.java
new file mode 100644
index 0000000..544cf42
--- /dev/null
+++ b/src/test/java/org/sadisamir/ndarray/demo/NdArrayDemoTest.java
@@ -0,0 +1,16 @@
+package org.sadisamir.ndarray.demo;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+
+/**
+ * Tests for NdArrayDemo to ensure demo execution completes without errors.
+ */
+class NdArrayDemoTest {
+
+ @Test
+ void testMainExecutesWithoutException() {
+ assertDoesNotThrow(() -> NdArrayDemo.main(new String[]{}));
+ }
+}
From 4104bb37d4b195b4af5dc0d3f2f51ae2363be211 Mon Sep 17 00:00:00 2001
From: sMouaad <93816869+sMouaad@users.noreply.github.com>
Date: Sat, 4 Apr 2026 20:13:25 +0200
Subject: [PATCH 12/12] fix: jar now runs with SLF4J included to make the
logger work
---
.gitignore | 1 +
pom.xml | 21 +++++++++++++++++++++
2 files changed, 22 insertions(+)
diff --git a/.gitignore b/.gitignore
index 2f7896d..8b8c81d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
target/
+dependency-reduced-pom.xml
diff --git a/pom.xml b/pom.xml
index ea519d5..da8b5f4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -73,6 +73,27 @@
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 3.6.0
+
+
+ package
+
+ shade
+
+
+
+
+ org.sadisamir.ndarray.demo.NdArrayDemo
+
+
+
+
+
+
+
org.jacoco
jacoco-maven-plugin