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
59 changes: 12 additions & 47 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -156,57 +156,22 @@ jobs:
SIGNING_KEY: ${{ secrets.SIGNING_KEY }}
SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }}

- name: Publish krelay
run: ./gradlew :krelay:publishAllPublicationsToOSSRHRepository --no-daemon
# One signed bundle for ALL modules -> one Central Portal deployment, validated and published
# together. (Per-module Gradle publishes left some artifacts out of the 2.3.0 deployment.)
- name: Build bundle and upload to Central Portal
run: scripts/build-maven-bundle.sh --upload automatic
env:
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
CENTRAL_USERNAME: ${{ secrets.OSSRH_USERNAME }}
CENTRAL_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
SIGNING_KEY: ${{ secrets.SIGNING_KEY }}
SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }}

- name: Publish krelay-flow
run: ./gradlew :krelay-flow:publishAllPublicationsToOSSRHRepository --no-daemon
env:
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
SIGNING_KEY: ${{ secrets.SIGNING_KEY }}
SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }}

- name: Publish krelay-compose
run: ./gradlew :krelay-compose:publishAllPublicationsToOSSRHRepository --no-daemon
env:
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
SIGNING_KEY: ${{ secrets.SIGNING_KEY }}
SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }}

- name: Publish krelay-testing
run: ./gradlew :krelay-testing:publishAllPublicationsToOSSRHRepository --no-daemon
env:
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
SIGNING_KEY: ${{ secrets.SIGNING_KEY }}
SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }}

- name: Publish krelay-bom
run: ./gradlew :krelay-bom:publishAllPublicationsToOSSRHRepository --no-daemon
env:
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
SIGNING_KEY: ${{ secrets.SIGNING_KEY }}
SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }}

# Legacy OSSRH (s01) was retired; uploads now land in the Central Portal
# staging API and must be handed over to the Portal to be published.
- name: Hand staged repository over to Central Portal
run: |
AUTH=$(printf '%s:%s' "$OSSRH_USERNAME" "$OSSRH_PASSWORD" | base64)
curl --fail-with-body -X POST \
-H "Authorization: Bearer $AUTH" \
"https://ossrh-staging-api.central.sonatype.com/manual/upload/defaultRepository/dev.brewkits?publishing_type=automatic"
env:
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
- name: Upload bundle as workflow artifact
if: always()
uses: actions/upload-artifact@v7
with:
name: maven-bundle
path: krelay-v*-maven-bundle.zip

# ──────────────────────────────────────────────────────────────────────────
github-release:
Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Changed
- **Release publishing**: `scripts/build-maven-bundle.sh` builds every module into a single signed Maven bundle (one Central Portal deployment) and `release.yml` uses it. Per-module Gradle publishes left 12 artifacts (`krelay-testing*`, `krelay-bom`, `krelay-flow-android/iosarm64/iossimulatorarm64`, `krelay-compose-wasm-js`) out of the 2.3.0 deployment. See `docs/RELEASING.md`.

---

## [2.3.0] - 2026-10-01
Expand Down
22 changes: 22 additions & 0 deletions docs/RELEASING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Releasing KRelay

1. Bump `version` in all five modules (`krelay`, `krelay-flow`, `krelay-compose`, `krelay-testing`, `krelay-bom`), update `CHANGELOG.md`, merge to `main`.
2. Tag: `git tag -a vX.Y.Z -m "KRelay X.Y.Z" && git push origin vX.Y.Z`. The **Release** workflow tests, builds and publishes.

## Maven bundle script

`scripts/build-maven-bundle.sh` signs and gathers **all** modules into one zip, so Maven Central gets
a single deployment containing every artifact.

```bash
scripts/build-maven-bundle.sh # build + verify + zip -> krelay-vX.Y.Z-maven-bundle.zip
scripts/build-maven-bundle.sh --skip-build # reuse build/maven-central-staging
scripts/build-maven-bundle.sh --only-missing # zip only what is not on Maven Central yet
CENTRAL_USERNAME=... CENTRAL_PASSWORD=... \
scripts/build-maven-bundle.sh --upload manual # upload via the Central Portal API (manual = you click Publish)
```

- Signing key: `signing.key` / `signing.password` in `~/.gradle/gradle.properties`, or `SIGNING_KEY` / `SIGNING_PASSWORD`.
- `CENTRAL_*` are a Central Portal **user token**. In CI they come from the `OSSRH_USERNAME` / `OSSRH_PASSWORD` secrets of the `maven-central` environment.
- The script refuses to run if module versions differ and fails if any artifact lacks a signature or checksum.
- After publishing, confirm all artifacts resolve: `krelay`, `krelay-flow`, `krelay-compose`, `krelay-testing`, `krelay-bom` and their `-jvm`, `-android`, `-ios*`, `-wasm-js` variants.
107 changes: 107 additions & 0 deletions scripts/build-maven-bundle.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#!/usr/bin/env bash
#
# Builds ONE Maven Central bundle (zip) containing every KRelay module, signed and checksummed.
#
# scripts/build-maven-bundle.sh # build + verify + zip everything
# scripts/build-maven-bundle.sh --skip-build # reuse build/maven-central-staging
# scripts/build-maven-bundle.sh --only-missing # zip only artifacts not yet on Maven Central
# scripts/build-maven-bundle.sh --upload manual|automatic
# # also upload via the Central Portal API
# # (needs CENTRAL_USERNAME / CENTRAL_PASSWORD = Portal user token)
#
# Signing: ~/.gradle/gradle.properties (signing.key / signing.password) or SIGNING_KEY / SIGNING_PASSWORD.
# Output: krelay-v<version>-maven-bundle.zip in the repository root (git-ignored).
#
# Why one bundle: publishing modules in separate Gradle runs left some artifacts out of the
# Central deployment for 2.3.0. A single zip is one deployment, validated and published together.

set -euo pipefail

ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$ROOT"

SKIP_BUILD=0
ONLY_MISSING=0
UPLOAD=""
while [ $# -gt 0 ]; do
case "$1" in
--skip-build) SKIP_BUILD=1 ;;
--only-missing) ONLY_MISSING=1 ;;
--upload) UPLOAD="${2:?--upload needs 'manual' or 'automatic'}"; shift ;;
-h|--help) sed -n '2,17p' "$0"; exit 0 ;;
*) echo "Unknown option: $1" >&2; exit 2 ;;
esac
shift
done

GROUP_PATH="dev/brewkits"
MODULES=(krelay krelay-flow krelay-compose krelay-testing krelay-bom)
STAGING="$ROOT/build/maven-central-staging"

VERSION="$(sed -n 's/^version = "\(.*\)"/\1/p' krelay/build.gradle.kts | head -1)"
[ -n "$VERSION" ] || { echo "Cannot read version from krelay/build.gradle.kts" >&2; exit 1; }
for m in "${MODULES[@]}"; do
v="$(sed -n 's/^version = "\(.*\)"/\1/p' "$m/build.gradle.kts" | head -1)"
[ "$v" = "$VERSION" ] || { echo "Version mismatch: $m is $v, krelay is $VERSION" >&2; exit 1; }
done
echo "==> KRelay $VERSION"

# 1. Build + sign every module into the local staging repository
if [ "$SKIP_BUILD" -eq 0 ]; then
rm -rf "$STAGING"
TASKS=()
for m in "${MODULES[@]}"; do TASKS+=(":$m:publishAllPublicationsToMavenCentralLocalRepository"); done
./gradlew "${TASKS[@]}" --no-daemon -q
fi
[ -d "$STAGING/$GROUP_PATH" ] || { echo "No staged artifacts in $STAGING" >&2; exit 1; }

# 2. Verify: every artifact file is signed and has checksums; filter by version
bad=0
while IFS= read -r f; do
[ -f "$f.asc" ] && [ -f "$f.md5" ] && [ -f "$f.sha1" ] || { echo "Missing signature/checksum: $f" >&2; bad=1; }
done < <(find "$STAGING/$GROUP_PATH" -type f ! -name '*.asc' ! -name '*.md5' ! -name '*.sha*' ! -name 'maven-metadata*')
[ "$bad" -eq 0 ] || exit 1

# 3. Select artifacts for the bundle
WORK="$ROOT/build/maven-bundle-work"
rm -rf "$WORK"; mkdir -p "$WORK/$GROUP_PATH"
count=0
for dir in "$STAGING/$GROUP_PATH"/*/; do
artifact="$(basename "$dir")"
[ -d "$dir$VERSION" ] || continue
if [ "$ONLY_MISSING" -eq 1 ]; then
code="$(curl -s -o /dev/null -w '%{http_code}' "https://repo1.maven.org/maven2/$GROUP_PATH/$artifact/$VERSION/$artifact-$VERSION.pom")"
if [ "$code" = "200" ]; then echo " skip (already on Central): $artifact"; continue; fi
fi
mkdir -p "$WORK/$GROUP_PATH/$artifact"
cp -R "$dir$VERSION" "$WORK/$GROUP_PATH/$artifact/"
count=$((count + 1))
done
[ "$count" -gt 0 ] || { echo "Nothing to bundle." >&2; exit 1; }

# 4. Zip with the Maven layout at the archive root
SUFFIX=""; [ "$ONLY_MISSING" -eq 1 ] && SUFFIX="-missing"
ZIP="$ROOT/krelay-v$VERSION$SUFFIX-maven-bundle.zip"
rm -f "$ZIP"
( cd "$WORK" && zip -qr "$ZIP" dev )
rm -rf "$WORK"
echo "==> $count artifact(s) -> $ZIP ($(du -h "$ZIP" | cut -f1))"

# 5. Optional upload to the Central Portal (one deployment)
if [ -n "$UPLOAD" ]; then
case "$UPLOAD" in
manual) TYPE=USER_MANAGED ;;
automatic) TYPE=AUTOMATIC ;;
*) echo "--upload must be 'manual' or 'automatic'" >&2; exit 2 ;;
esac
: "${CENTRAL_USERNAME:?set CENTRAL_USERNAME (Portal user token name)}"
: "${CENTRAL_PASSWORD:?set CENTRAL_PASSWORD (Portal user token password)}"
TOKEN="$(printf '%s:%s' "$CENTRAL_USERNAME" "$CENTRAL_PASSWORD" | base64)"
NAME="$(basename "$ZIP" .zip)"
ID="$(curl -sS --fail-with-body -X POST \
-H "Authorization: Bearer $TOKEN" \
-F "bundle=@$ZIP" \
"https://central.sonatype.com/api/v1/publisher/upload?name=$NAME&publishingType=$TYPE")"
echo "==> Uploaded. Deployment id: $ID"
echo " Status: curl -X POST -H 'Authorization: Bearer <token>' 'https://central.sonatype.com/api/v1/publisher/status?id=$ID'"
fi
Loading