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
73 changes: 73 additions & 0 deletions .github/scripts/validate-published-poms.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#!/usr/bin/env bash
# Fails the build if any published SKaiNET POM contains invalid coordinates.
#
# Catches the class of bug shipped in 0.19.0, where `skainet-backend-cpu`'s POM
# declared `sk.ainet:skainet-backend-api-jvm:unspecified` because
# `skainet-backend-api` was not configured to publish and the root
# `allprojects { group = "sk.ainet" }` disagreed with `GROUP=sk.ainet.core`.
#
# Two checks per generated POM under ~/.m2/repository/sk/ainet/core/**:
# 1. No `<version>unspecified</version>` anywhere in the POM.
# 2. Every `<dependency>` whose `<artifactId>` starts with `skainet-` uses
# `<groupId>sk.ainet.core</groupId>` — `project(...)` deps on sibling
# modules must resolve to the same publish group.

set -euo pipefail

REPO_ROOT="${HOME}/.m2/repository/sk/ainet/core"

if [[ ! -d "${REPO_ROOT}" ]]; then
echo "ERROR: no published artifacts found under ${REPO_ROOT}" >&2
echo "Did ./gradlew publishToMavenLocal run successfully?" >&2
exit 1
fi

mapfile -t POMS < <(find "${REPO_ROOT}" -type f -name '*.pom' | sort)

if [[ ${#POMS[@]} -eq 0 ]]; then
echo "ERROR: no .pom files under ${REPO_ROOT}" >&2
exit 1
fi

echo "Scanning ${#POMS[@]} published POMs..."

report_file="$(mktemp)"
trap 'rm -f "${report_file}"' EXIT

for pom in "${POMS[@]}"; do
rel="${pom#${REPO_ROOT}/}"

if grep -Fq '<version>unspecified</version>' "${pom}"; then
{
echo "FAIL ${rel}: contains <version>unspecified</version>"
grep -n '<version>unspecified</version>' "${pom}" | sed 's/^/ /'
} >> "${report_file}"
fi

bad_deps="$(awk '
/<dependency>/ { inDep=1; block=""; next }
inDep { block = block "\n" $0 }
/<\/dependency>/ {
inDep=0
if (block ~ /<artifactId>skainet-/ && block !~ /<groupId>sk\.ainet\.core<\/groupId>/) {
print block
}
}
' "${pom}")"

if [[ -n "${bad_deps}" ]]; then
{
echo "FAIL ${rel}: skainet-* dependency with non-sk.ainet.core group"
printf '%s\n' "${bad_deps}" | sed 's/^/ /'
} >> "${report_file}"
fi
done

if [[ -s "${report_file}" ]]; then
cat "${report_file}" >&2
echo "" >&2
echo "POM validation failed. See the 0.19.1 CHANGELOG entry for the regression this check prevents." >&2
exit 1
fi

echo "All ${#POMS[@]} POMs look good."
38 changes: 38 additions & 0 deletions .github/workflows/verify-poms.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Verify published POMs

on: [push, pull_request]

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
verify-poms:
name: Publish to Maven local and validate POM coordinates
runs-on: ubuntu-latest
timeout-minutes: 45

steps:
- name: Checkout
uses: actions/checkout@v6

- name: Copy CI gradle.properties
run: mkdir -p ~/.gradle ; cp .github/ci-gradle.properties ~/.gradle/gradle.properties

- name: Set up JDK 25
uses: actions/setup-java@v5
with:
distribution: 'zulu'
java-version: 25

- name: Publish to Maven local
env:
GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx4g -Dfile.encoding=UTF-8"
run: |
./gradlew --no-daemon --stacktrace --no-configuration-cache \
-PRELEASE_SIGNING_ENABLED=false \
-PsignAllPublications=false \
publishToMavenLocal

- name: Validate POM coordinates
run: ./.github/scripts/validate-published-poms.sh
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@

## [Unreleased]

## [0.19.1] - 2026-04-21

### Fixed

- **Broken POM for `skainet-backend-cpu`**: The 0.19.0 POM for `sk.ainet.core:skainet-backend-cpu-*` declared a runtime dependency on `sk.ainet:skainet-backend-api-jvm:unspecified` — wrong group coordinate and no valid version, because `skainet-backend-api` was not configured to publish and the root `allprojects { group = "sk.ainet" }` disagreed with the `GROUP=sk.ainet.core` used by vanniktech's maven publish plugin. Consumers pulling 0.19.0 hit unresolved-dependency errors. Fixed by:
- Applying `vanniktech.mavenPublish` and setting `POM_ARTIFACT_ID=skainet-backend-api` on `skainet-backend-api` so it is actually published alongside the BOM entry that already referenced it.
- Aligning `allprojects { group = "sk.ainet.core" }` with the `GROUP` property and pinning `version` from `VERSION_NAME` so `project(...)` coordinates in generated POMs are consistent.
- **CI guard**: New `verify-published-poms` job publishes to the local Maven repository and fails the build if any generated `.pom` contains `<version>unspecified</version>` or references a project-local group outside `sk.ainet.core`, preventing a regression of this class of coordinate bug.

## [0.19.0] - 2026-04-20

### Added
Expand Down
3 changes: 2 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ plugins {
}

allprojects {
group = "sk.ainet"
group = "sk.ainet.core"
version = providers.gradleProperty("VERSION_NAME").getOrElse("unspecified")
}

// Require JDK 21+ but allow any newer version (produces Java 21 bytecode via --release / jvmTarget)
Expand Down
1 change: 1 addition & 0 deletions skainet-backends/skainet-backend-api/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget
plugins {
alias(libs.plugins.kotlinMultiplatform)
alias(libs.plugins.androidMultiplatformLibrary)
alias(libs.plugins.vanniktech.mavenPublish)
id("sk.ainet.dokka")
}

Expand Down
2 changes: 2 additions & 0 deletions skainet-backends/skainet-backend-api/gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
POM_ARTIFACT_ID=skainet-backend-api
POM_NAME=skainet backend-neutral API
Loading