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
34 changes: 33 additions & 1 deletion .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Project Overview

PolyBus is a **polyglot messaging framework** that enables seamless communication between applications written in different programming languages. It provides unified interfaces across TypeScript, Python, and .NET (with PHP planned) for building interoperable distributed systems and microservices.
PolyBus is a **polyglot messaging framework** that enables seamless communication between applications written in different programming languages. It provides unified interfaces across TypeScript, Python, .NET, and Kotlin (with PHP planned) for building interoperable distributed systems and microservices.

## Core Architecture Principles

Expand Down Expand Up @@ -111,6 +111,28 @@ class IPolyBus(ABC):
- Use `./lint.sh` for code quality checks
- Follow `.editorconfig` and `.DotSettings` conventions

### Kotlin (`src/kotlin/`)

**Technology Stack:**
- Kotlin/JVM 2.1.x
- JDK 17 toolchain
- Gradle Kotlin DSL (`build.gradle.kts`)
- JUnit 5 + Kotlin test + JaCoCo coverage

**Coding Conventions:**
- Use coroutines (`suspend`) for async workflows
- Keep naming consistent with cross-language parity (`IPolyBus`, `PolyBusBuilder`, `createTransaction`)
- Prefer immutable values and data classes for message models

**Testing and Coverage:**
- Run tests with `gradle test`
- Generate coverage with `gradle coverage`
- JaCoCo XML report path: `build/reports/jacoco/test/jacocoTestReport.xml`

**Publishing Notes:**
- Use Gradle publish workflow (`gradle publish`) with repository credentials from CI secrets
- Keep package coordinates stable unless intentionally changing group/artifact naming

## Cross-Language Consistency

### Naming Conventions
Expand Down Expand Up @@ -351,6 +373,16 @@ dotnet test # Run tests
./lint.sh # Run linting
```

### Kotlin
```bash
cd src/kotlin
gradle clean # Clean build outputs
gradle build # Compile and run checks
gradle test # Run tests
gradle coverage # Generate JaCoCo XML/HTML coverage
gradle publish # Publish package (CI credentials required)
```

## Resources

- **Main README**: `/README.md`
Expand Down
36 changes: 35 additions & 1 deletion .github/workflows/pr-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,39 @@ jobs:
flags: dotnet
name: dotnet-coverage

kotlin-tests:
name: Kotlin Tests
runs-on: ubuntu-latest
defaults:
run:
working-directory: src/kotlin

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'

- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3

- name: Build
run: ./gradlew build

- name: Run tests with coverage
run: ./gradlew coverage
Comment thread
CyAScott marked this conversation as resolved.

- name: Upload Kotlin coverage
uses: codecov/codecov-action@v4
with:
files: ./src/kotlin/build/reports/jacoco/test/jacocoTestReport.xml
flags: kotlin
name: kotlin-coverage

python-tests:
name: Python Tests
runs-on: ubuntu-latest
Expand Down Expand Up @@ -108,7 +141,7 @@ jobs:
coverage-summary:
name: Coverage Summary
runs-on: ubuntu-latest
needs: [dotnet-tests, python-tests, typescript-tests]
needs: [dotnet-tests, python-tests, typescript-tests, kotlin-tests]
if: always()

steps:
Expand All @@ -120,3 +153,4 @@ jobs:
echo "- ✅ .NET Tests: ${{ needs.dotnet-tests.result }}" >> $GITHUB_STEP_SUMMARY
echo "- ✅ Python Tests: ${{ needs.python-tests.result }}" >> $GITHUB_STEP_SUMMARY
echo "- ✅ TypeScript Tests: ${{ needs.typescript-tests.result }}" >> $GITHUB_STEP_SUMMARY
echo "- ✅ Kotlin Tests: ${{ needs.kotlin-tests.result }}" >> $GITHUB_STEP_SUMMARY
90 changes: 84 additions & 6 deletions .github/workflows/release-and-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,29 @@ on:
paths:
- 'src/**'
- '.github/workflows/release-and-publish.yml'
pull_request:
paths:
- 'src/**'
- '.github/workflows/release-and-publish.yml'

permissions:
contents: write
packages: write
id-token: write

jobs:
pr-status:
name: PR Status
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
steps:
- name: Skip release workflow on pull requests
run: echo "Release and publish only runs on pushes to main."

# Determine version using GitVersion
determine-version:
name: Determine Version
if: github.event_name == 'push'
runs-on: ubuntu-latest
outputs:
version: ${{ steps.gitversion.outputs.semVer }}
Expand Down Expand Up @@ -67,7 +80,7 @@ jobs:
name: Build and Test All Packages
runs-on: ubuntu-latest
needs: determine-version
if: needs.determine-version.outputs.should_release == 'true'
if: github.event_name == 'push' && needs.determine-version.outputs.should_release == 'true'
steps:
- name: Checkout code
uses: actions/checkout@v4
Expand Down Expand Up @@ -117,6 +130,22 @@ jobs:
dotnet test --configuration Release
dotnet pack --configuration Release --output ./nupkg

# Kotlin build and test
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'

- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3

- name: Build Kotlin package
working-directory: src/kotlin
run: |
./gradlew clean build
./gradlew coverage

# Upload build artifacts
- name: Upload TypeScript artifact
uses: actions/upload-artifact@v4
Expand All @@ -136,12 +165,18 @@ jobs:
name: dotnet-package
path: src/dotnet/PolyBus/nupkg/

- name: Upload Kotlin artifact
uses: actions/upload-artifact@v4
with:
name: kotlin-package
path: src/kotlin/build/libs/

# Publish to npm
publish-npm:
name: Publish to npm
runs-on: ubuntu-latest
needs: [determine-version, build-and-test]
if: needs.determine-version.outputs.should_release == 'true'
if: github.event_name == 'push' && needs.determine-version.outputs.should_release == 'true'
permissions:
id-token: write
contents: read
Expand Down Expand Up @@ -179,7 +214,7 @@ jobs:
name: Publish to PyPI
runs-on: ubuntu-latest
needs: [determine-version, build-and-test]
if: needs.determine-version.outputs.should_release == 'true'
if: github.event_name == 'push' && needs.determine-version.outputs.should_release == 'true'
permissions:
id-token: write
steps:
Expand Down Expand Up @@ -215,7 +250,7 @@ jobs:
name: Publish to NuGet
runs-on: ubuntu-latest
needs: [determine-version, build-and-test]
if: needs.determine-version.outputs.should_release == 'true'
if: github.event_name == 'push' && needs.determine-version.outputs.should_release == 'true'
steps:
- name: Checkout code
uses: actions/checkout@v4
Expand Down Expand Up @@ -243,12 +278,51 @@ jobs:
run: |
dotnet nuget push "./nupkg/*.nupkg" --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate

# Publish Gradle package
publish-gradle:
name: Publish Gradle Package
runs-on: ubuntu-latest
needs: [determine-version, build-and-test]
if: github.event_name == 'push' && needs.determine-version.outputs.should_release == 'true'
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'

- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3

- name: Update package version
working-directory: src/kotlin
run: |
sed -i "s/^version = .*/version = \"${{ needs.determine-version.outputs.version }}\"/" build.gradle.kts

- name: Build and publish
working-directory: src/kotlin
env:
MAVEN_REPOSITORY_URL: ${{ secrets.MAVEN_REPOSITORY_URL }}
MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
run: |
chmod +x ./gradlew
./gradlew clean build
if ./gradlew tasks --all | grep -qE '(^|[[:space:]])publish([[:space:]]|$)'; then
./gradlew publish -PmavenRepoUrl="$MAVEN_REPOSITORY_URL" -PmavenUsername="$MAVEN_USERNAME" -PmavenPassword="$MAVEN_PASSWORD"
else
echo "Skipping Gradle publish: no 'publish' task is configured in src/kotlin."
fi

# Summary job
publish-summary:
name: Publish Summary
runs-on: ubuntu-latest
needs: [determine-version, publish-pypi, publish-nuget]
if: always() && needs.determine-version.outputs.should_release == 'true'
needs: [determine-version, publish-npm, publish-pypi, publish-nuget, publish-gradle]
if: github.event_name == 'push' && always() && needs.determine-version.outputs.should_release == 'true'
steps:
- name: Summary
run: |
Expand All @@ -259,6 +333,7 @@ jobs:
echo "- 📦 **npm**: ${{ needs.publish-npm.result }}" >> $GITHUB_STEP_SUMMARY
echo "- 🐍 **PyPI**: ${{ needs.publish-pypi.result }}" >> $GITHUB_STEP_SUMMARY
echo "- ⚡ **NuGet**: ${{ needs.publish-nuget.result }}" >> $GITHUB_STEP_SUMMARY
echo "- 🟠 **Gradle/Maven**: ${{ needs.publish-gradle.result }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Installation Commands" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
Expand All @@ -271,4 +346,7 @@ jobs:
echo "" >> $GITHUB_STEP_SUMMARY
echo "# .NET" >> $GITHUB_STEP_SUMMARY
echo "dotnet add package PolyBus --version ${{ needs.determine-version.outputs.version }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "# Kotlin (Gradle/Maven)" >> $GITHUB_STEP_SUMMARY
echo "implementation(\"com.cyascott:poly-bus:${{ needs.determine-version.outputs.version }}\")" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Gradle
**/.gradle/*

# Environment
.env
.env.local
58 changes: 56 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ PolyBus provides a unified interface for sending and receiving messages between

## 🌟 Key Features

- **🔄 Multi-Language Support**: Native implementations for TypeScript, Python, and .NET
- **🔄 Multi-Language Support**: Native implementations for TypeScript, Python, .NET, and Kotlin
- **🚀 Flexible Transport**: Pluggable transport layer supporting various messaging systems
- **⚡ Async/Await**: Modern asynchronous APIs in all language implementations
- **🔌 Middleware Pipeline**: Extensible handler chains for incoming and outgoing messages
Expand All @@ -26,6 +26,7 @@ PolyBus provides a unified interface for sending and receiving messages between
| **TypeScript/JavaScript** | Node.js 14+ | ✅ Stable | CommonJS, ESM, UMD |
| **Python** | 3.8-3.12 | ✅ Stable | PyPI package |
| **.NET** | .NET Standard 2.1 | ✅ Stable | NuGet package |
| **Kotlin** | JDK 17+ | ✅ Stable | Gradle/JVM package |
| **PHP** | 8.0+ | 🚧 Planned | - |

## 🚀 Quick Start
Expand Down Expand Up @@ -56,6 +57,38 @@ await transaction.commit();
await bus.stop();
```

### Kotlin

```kotlin
import kotlinx.coroutines.runBlocking
import polybus.PolyBusBuilder
import polybus.transport.transactions.messages.MessageInfo
import polybus.transport.transactions.messages.MessageType
import polybus.transport.transactions.messages.handlers.serializers.JsonHandlers

@MessageInfo(MessageType.EVENT, "users", "user-created", 1, 0, 0)
data class UserCreated(val userId: Int)

fun main() = runBlocking {
val builder = PolyBusBuilder()
builder.name = "my-service"

val jsonHandlers = JsonHandlers()
builder.incomingPipeline.add(jsonHandlers::deserializer)
builder.outgoingPipeline.add(jsonHandlers::serializer)
builder.messages.add(UserCreated::class.java)

val bus = builder.build()
bus.start()

val transaction = bus.createOutgoingTransaction()
transaction.add(UserCreated(userId = 123))
transaction.commit()

bus.stop()
}
```

### Python

```python
Expand Down Expand Up @@ -217,6 +250,18 @@ dotnet test

See [.NET README](src/dotnet/README.md) for detailed development instructions.

### Kotlin Development

```bash
cd src/kotlin
gradle clean
gradle build
gradle test
gradle coverage
```

See [Kotlin README](src/kotlin/README.md) for detailed development instructions.

## 🧪 Testing

All implementations include comprehensive test suites:
Expand Down Expand Up @@ -248,6 +293,15 @@ pip install poly-bus
dotnet add package PolyBus
```

### Kotlin

```bash
cd src/kotlin
gradle build
```

For Kotlin package usage and publishing details, see [Kotlin README](src/kotlin/README.md).

## 🤝 Contributing

We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details on:
Expand Down Expand Up @@ -277,6 +331,6 @@ This project is licensed under the terms specified in the [LICENSE](LICENSE) fil

## ⭐ Project Status

PolyBus is actively maintained and production-ready for TypeScript, Python, and .NET implementations. PHP support is planned for future releases.
PolyBus is actively maintained and production-ready for TypeScript, Python, .NET, and Kotlin implementations. PHP support is planned for future releases.

If you find PolyBus useful, please consider giving it a star ⭐ on GitHub!
Loading
Loading