Skip to content

Commit 9554d13

Browse files
feat: migrate Hyperion Java client from Gradle to Maven
1 parent e333bb9 commit 9554d13

File tree

15 files changed

+1132
-823
lines changed

15 files changed

+1132
-823
lines changed
Lines changed: 253 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1-
name: Hyperion - Java Client Publish Snapshots
1+
name: Hyperion Java Client - CI/CD
2+
3+
# Required GitHub Secrets:
4+
# - GITHUB_TOKEN: Automatically provided by GitHub for GitHub Packages
5+
# - OSSRH_USERNAME: Sonatype OSSRH username for Maven Central
6+
# - OSSRH_PASSWORD: Sonatype OSSRH password for Maven Central
7+
# - GPG_KEY: Base64 encoded GPG private key (gpg --armor --export-secret-keys KEY_ID | base64 -w 0)
8+
# - GPG_PASSPHRASE: GPG key passphrase
29

310
permissions:
411
contents: read
@@ -10,115 +17,290 @@ on:
1017
- 'hyperion/java-client/**'
1118
- 'hyperion/app/protos/**'
1219
pull_request:
13-
branches: [main]
20+
branches: [main, develop]
1421
paths:
1522
- 'hyperion/java-client/**'
1623
- 'hyperion/app/protos/**'
1724
workflow_dispatch:
1825

1926
jobs:
20-
validate:
21-
name: Validate and Test
27+
build:
28+
name: Build & Test
2229
runs-on: ubuntu-latest
30+
outputs:
31+
should-publish: ${{ steps.check.outputs.should-publish }}
32+
version: ${{ steps.version.outputs.version }}
33+
branch-name: ${{ steps.version.outputs.branch-name }}
34+
is-snapshot: ${{ steps.version.outputs.is-snapshot }}
35+
2336
steps:
24-
- name: Checkout repository
37+
- name: Checkout
2538
uses: actions/checkout@v4
2639

27-
- name: Set up JDK 17
40+
- name: Setup JDK 17
2841
uses: actions/setup-java@v4
2942
with:
3043
java-version: '17'
3144
distribution: 'temurin'
3245

33-
- name: Setup Gradle
34-
uses: gradle/actions/setup-gradle@v4
46+
- name: Cache Maven
47+
uses: actions/cache@v4
3548
with:
36-
gradle-version: wrapper
49+
path: ~/.m2
50+
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
3751

38-
- name: Build and test
52+
- name: Determine version and publishing strategy
53+
id: version
3954
working-directory: hyperion/java-client
40-
run: ./gradlew build --no-daemon --parallel
41-
42-
- name: Upload build artifacts
43-
uses: actions/upload-artifact@v4
44-
if: always()
45-
with:
46-
name: build-artifacts
47-
path: |
48-
hyperion/java-client/build/libs/
49-
hyperion/java-client/build/reports/
50-
retention-days: 7
55+
run: |
56+
# Get base version from pom.xml (always 1.1.0)
57+
BASE_VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)
58+
echo "📋 Base version from pom.xml: $BASE_VERSION"
59+
60+
# Get branch name (handle PR refs properly)
61+
if [[ "${{ github.ref }}" == refs/pull/* ]]; then
62+
BRANCH_NAME="${{ github.head_ref }}"
63+
else
64+
BRANCH_NAME="${{ github.ref_name }}"
65+
fi
66+
echo "🌿 Branch: $BRANCH_NAME"
67+
68+
# Determine version strategy based on branch
69+
if [[ "$BRANCH_NAME" == "main" ]] || [[ "$BRANCH_NAME" == "develop" ]]; then
70+
# Stable branches: use base version for releases
71+
FINAL_VERSION="$BASE_VERSION"
72+
IS_SNAPSHOT="false"
73+
echo "🎯 Stable branch detected: will publish release version $FINAL_VERSION"
74+
else
75+
# Feature branches: use dynamic branch-based snapshots
76+
# Use EXACT same sanitization as local Maven build
77+
SANITIZED_BRANCH=$(echo "$BRANCH_NAME" | sed 's/[^a-zA-Z0-9]/-/g' | tr '[:upper:]' '[:lower:]')
78+
FINAL_VERSION="${BASE_VERSION}-${SANITIZED_BRANCH}-SNAPSHOT"
79+
IS_SNAPSHOT="true"
80+
echo "🔨 Feature branch detected: will publish snapshot $FINAL_VERSION"
81+
fi
82+
83+
echo "version=$FINAL_VERSION" >> $GITHUB_OUTPUT
84+
echo "branch-name=$BRANCH_NAME" >> $GITHUB_OUTPUT
85+
echo "is-snapshot=$IS_SNAPSHOT" >> $GITHUB_OUTPUT
86+
echo "base-version=$BASE_VERSION" >> $GITHUB_OUTPUT
87+
88+
- name: Check publishing rules
89+
id: check
90+
run: |
91+
BRANCH_NAME="${{ steps.version.outputs.branch-name }}"
92+
EVENT="${{ github.event_name }}"
93+
94+
# Publish on push events (feature branches → snapshots, stable branches → releases)
95+
if [[ "$EVENT" == "push" ]]; then
96+
echo "should-publish=true" >> $GITHUB_OUTPUT
97+
if [[ "${{ steps.version.outputs.is-snapshot }}" == "true" ]]; then
98+
echo "✅ Will publish feature snapshot to GitHub Packages"
99+
else
100+
echo "✅ Will publish release to GitHub Packages + Maven Central"
101+
fi
102+
else
103+
echo "should-publish=false" >> $GITHUB_OUTPUT
104+
echo "ℹ️ PR: Build only, no publishing"
105+
fi
106+
107+
- name: Build & Test
108+
working-directory: hyperion/java-client
109+
run: |
110+
if [[ "${{ steps.version.outputs.is-snapshot }}" == "true" ]]; then
111+
echo "🔨 Building feature branch with local dynamic versioning"
112+
mvn clean compile test package --no-transfer-progress
113+
else
114+
echo "🎯 Building stable release with base version"
115+
mvn clean compile test package -DskipLocalVersioning=true --no-transfer-progress
116+
fi
51117
52-
publish-snapshot:
53-
name: Publish Snapshot to GitHub Packages
54-
needs: validate
118+
publish-snapshots:
119+
name: Publish Snapshots
120+
needs: build
55121
runs-on: ubuntu-latest
56-
122+
if: needs.build.outputs.should-publish == 'true' && needs.build.outputs.is-snapshot == 'true'
123+
57124
steps:
58-
- name: Checkout repository
125+
- name: Checkout
59126
uses: actions/checkout@v4
60127

61-
- name: Set up JDK 17
128+
- name: Setup JDK 17
62129
uses: actions/setup-java@v4
63130
with:
64131
java-version: '17'
65132
distribution: 'temurin'
66133

67-
- name: Setup Gradle
68-
uses: gradle/actions/setup-gradle@v4
134+
- name: Cache Maven
135+
uses: actions/cache@v4
69136
with:
70-
gradle-version: wrapper
137+
path: ~/.m2
138+
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
139+
140+
- name: Configure Maven for GitHub Packages
141+
run: |
142+
mkdir -p ~/.m2
143+
cat > ~/.m2/settings.xml << 'EOF'
144+
<settings>
145+
<servers>
146+
<server>
147+
<id>github</id>
148+
<username>${{ github.actor }}</username>
149+
<password>${{ secrets.GITHUB_TOKEN }}</password>
150+
</server>
151+
</servers>
152+
</settings>
153+
EOF
71154
72-
- name: Set snapshot version
155+
- name: Publish Snapshot to GitHub Packages
73156
working-directory: hyperion/java-client
74157
run: |
75-
# Extract current version and build meaningful snapshot version
76-
CURRENT_VERSION=$(grep "^version = " build.gradle | sed "s/version = '\(.*\)'/\1/")
77-
DATE=$(date -u +"%Y%m%d")
78-
COMMIT_SHA=${GITHUB_SHA:0:7}
79-
80-
# Get meaningful branch name (handle PR refs properly)
81-
if [[ "$GITHUB_REF" == refs/pull/* ]]; then
82-
# For PRs, use the head branch name from the event
83-
BRANCH_NAME="${GITHUB_HEAD_REF}"
84-
else
85-
# For regular pushes, extract from ref
86-
BRANCH_NAME="${GITHUB_REF#refs/heads/}"
87-
fi
158+
echo "📦 Publishing snapshot ${{ needs.build.outputs.version }} to GitHub Packages"
159+
echo "🔨 Setting version to ${{ needs.build.outputs.version }} and deploying"
88160
89-
# Sanitize branch name for version compatibility
90-
BRANCH_SANITIZED=$(echo "$BRANCH_NAME" | sed 's/[^a-zA-Z0-9._-]/-/g' | sed 's/--*/-/g' | sed 's/^-\|-$//g')
161+
# Set the version to our calculated snapshot version
162+
mvn versions:set -DnewVersion="${{ needs.build.outputs.version }}" -DgenerateBackupPoms=false
91163
92-
# Remove existing -SNAPSHOT suffix if present
93-
if [[ "$CURRENT_VERSION" == *"-SNAPSHOT" ]]; then
94-
BASE_VERSION=${CURRENT_VERSION%-SNAPSHOT}
95-
else
96-
BASE_VERSION=$CURRENT_VERSION
97-
fi
164+
# Deploy to GitHub Packages
165+
mvn deploy -Pgithub --no-transfer-progress
166+
167+
publish-releases:
168+
name: Publish Releases
169+
needs: build
170+
runs-on: ubuntu-latest
171+
if: needs.build.outputs.should-publish == 'true' && needs.build.outputs.is-snapshot == 'false'
172+
173+
strategy:
174+
fail-fast: false
175+
matrix:
176+
target:
177+
- name: "Maven Central"
178+
profile: ""
179+
- name: "GitHub Packages"
180+
profile: "-Pgithub"
181+
182+
steps:
183+
- name: Checkout
184+
uses: actions/checkout@v4
185+
186+
- name: Setup JDK 17
187+
uses: actions/setup-java@v4
188+
with:
189+
java-version: '17'
190+
distribution: 'temurin'
98191

99-
# Build semantic snapshot version: base-branch-date-commit-SNAPSHOT
100-
NEW_VERSION="${BASE_VERSION}-${BRANCH_SANITIZED}-${DATE}-${COMMIT_SHA}-SNAPSHOT"
192+
- name: Cache Maven
193+
uses: actions/cache@v4
194+
with:
195+
path: ~/.m2
196+
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
101197

102-
echo "NEW_VERSION=${NEW_VERSION}" >> $GITHUB_ENV
103-
echo "📦 Publishing version: ${NEW_VERSION}"
104-
echo "🌿 Branch: ${BRANCH_NAME}"
105-
echo "📅 Date: ${DATE}"
106-
echo "🔗 Commit: ${COMMIT_SHA}"
198+
- name: Configure Maven
199+
run: |
200+
mkdir -p ~/.m2
201+
cat > ~/.m2/settings.xml << 'EOF'
202+
<settings>
203+
<servers>
204+
<server>
205+
<id>central</id>
206+
<username>${{ secrets.OSSRH_USERNAME }}</username>
207+
<password>${{ secrets.OSSRH_PASSWORD }}</password>
208+
</server>
209+
<server>
210+
<id>github</id>
211+
<username>${{ github.actor }}</username>
212+
<password>${{ secrets.GITHUB_TOKEN }}</password>
213+
</server>
214+
</servers>
215+
</settings>
216+
EOF
217+
218+
- name: Import GPG key
219+
if: matrix.target.profile == ''
220+
run: |
221+
# Import GPG private key for Maven Central signing
222+
echo "${{ secrets.GPG_KEY }}" | base64 -d | gpg --batch --import
107223
108-
# Update version in build.gradle
109-
sed -i "s/version = '.*'/version = '${NEW_VERSION}'/" build.gradle
224+
# Configure GPG for non-interactive use
225+
mkdir -p ~/.gnupg
226+
echo "use-agent" >> ~/.gnupg/gpg.conf
227+
echo "pinentry-mode loopback" >> ~/.gnupg/gpg.conf
228+
echo "allow-loopback-pinentry" >> ~/.gnupg/gpg-agent.conf
110229
111-
- name: Publish to GitHub Packages
230+
# Get the key ID automatically
231+
GPG_KEY_ID=$(gpg --list-secret-keys --keyid-format=long | grep -E "sec\s+[^/]+/([A-F0-9]{16})" | head -n1 | sed 's/.*\/\([A-F0-9]\{16\}\).*/\1/')
232+
if [[ -z "$GPG_KEY_ID" ]]; then
233+
echo "❌ Failed to detect GPG key ID"
234+
echo "Available keys:"
235+
gpg --list-secret-keys --keyid-format=long
236+
exit 1
237+
fi
238+
echo "🔑 Detected GPG Key ID: $GPG_KEY_ID"
239+
echo "GPG_KEY_ID=$GPG_KEY_ID" >> $GITHUB_ENV
240+
241+
- name: Publish Release to ${{ matrix.target.name }}
112242
working-directory: hyperion/java-client
113-
env:
114-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
115-
GITHUB_ACTOR: ${{ github.actor }}
116-
run: ./gradlew publishToGitHubPackages --no-daemon
117-
118-
- name: Create release summary
119243
run: |
120-
echo "## 📦 Package Published" >> $GITHUB_STEP_SUMMARY
244+
echo "📦 Publishing release ${{ needs.build.outputs.version }} to ${{ matrix.target.name }}"
245+
246+
if [[ "${{ matrix.target.profile }}" == "" ]]; then
247+
echo "🔐 Maven Central: Enabling GPG signing"
248+
mvn deploy -Prelease \
249+
-Dgpg.keyname="${GPG_KEY_ID}" \
250+
-Dgpg.passphrase="${{ secrets.GPG_PASSPHRASE }}" \
251+
--no-transfer-progress
252+
else
253+
echo "📦 GitHub Packages: Skipping GPG signing"
254+
mvn deploy ${{ matrix.target.profile }} --no-transfer-progress
255+
fi
256+
continue-on-error: ${{ matrix.target.profile == '-Pgithub' }}
257+
258+
summary:
259+
name: Summary
260+
needs: [build, publish-snapshots, publish-releases]
261+
runs-on: ubuntu-latest
262+
if: always()
263+
264+
steps:
265+
- name: Create Summary
266+
run: |
267+
echo "## 🚀 Hyperion Java Client CI/CD" >> $GITHUB_STEP_SUMMARY
121268
echo "" >> $GITHUB_STEP_SUMMARY
122-
echo "**Package:** \`de.tum.cit.aet.edutelligence:hyperion:${{ env.NEW_VERSION }}\`" >> $GITHUB_STEP_SUMMARY
269+
echo "| Field | Value |" >> $GITHUB_STEP_SUMMARY
270+
echo "|-------|-------|" >> $GITHUB_STEP_SUMMARY
271+
echo "| **Version** | \`${{ needs.build.outputs.version }}\` |" >> $GITHUB_STEP_SUMMARY
272+
echo "| **Branch** | \`${{ needs.build.outputs.branch-name }}\` |" >> $GITHUB_STEP_SUMMARY
273+
echo "| **Type** | ${{ needs.build.outputs.is-snapshot == 'true' && '📦 Snapshot' || '🎯 Release' }} |" >> $GITHUB_STEP_SUMMARY
274+
echo "| **Event** | \`${{ github.event_name }}\` |" >> $GITHUB_STEP_SUMMARY
275+
echo "| **Published** | ${{ needs.build.outputs.should-publish == 'true' && '✅ Yes' || '❌ No' }} |" >> $GITHUB_STEP_SUMMARY
123276
echo "" >> $GITHUB_STEP_SUMMARY
124-
echo "**Repository:** [GitHub Packages](https://github.com/ls1intum/edutelligence/packages)" >> $GITHUB_STEP_SUMMARY
277+
278+
if [[ "${{ needs.build.outputs.should-publish }}" == "true" ]]; then
279+
echo "### 📦 Usage" >> $GITHUB_STEP_SUMMARY
280+
echo '```xml' >> $GITHUB_STEP_SUMMARY
281+
echo '<dependency>' >> $GITHUB_STEP_SUMMARY
282+
echo ' <groupId>de.tum.cit.aet</groupId>' >> $GITHUB_STEP_SUMMARY
283+
echo ' <artifactId>hyperion</artifactId>' >> $GITHUB_STEP_SUMMARY
284+
echo " <version>${{ needs.build.outputs.version }}</version>" >> $GITHUB_STEP_SUMMARY
285+
echo '</dependency>' >> $GITHUB_STEP_SUMMARY
286+
echo '```' >> $GITHUB_STEP_SUMMARY
287+
288+
if [[ "${{ needs.build.outputs.is-snapshot }}" == "true" ]]; then
289+
echo "" >> $GITHUB_STEP_SUMMARY
290+
echo "### 🔨 Feature Branch Snapshot" >> $GITHUB_STEP_SUMMARY
291+
echo "- Published to **GitHub Packages only**" >> $GITHUB_STEP_SUMMARY
292+
echo "- Uses dynamic branch-based versioning: \`${{ needs.build.outputs.version }}\`" >> $GITHUB_STEP_SUMMARY
293+
echo "- Perfect for testing in Artemis feature branches" >> $GITHUB_STEP_SUMMARY
294+
echo "- No GPG signing required" >> $GITHUB_STEP_SUMMARY
295+
else
296+
echo "" >> $GITHUB_STEP_SUMMARY
297+
echo "### 🎯 Stable Release" >> $GITHUB_STEP_SUMMARY
298+
echo "- Published to **GitHub Packages + Maven Central**" >> $GITHUB_STEP_SUMMARY
299+
echo "- Uses base version from pom.xml: \`${{ needs.build.outputs.version }}\`" >> $GITHUB_STEP_SUMMARY
300+
echo "- **GPG signed** for Maven Central" >> $GITHUB_STEP_SUMMARY
301+
echo "- Ready for production use" >> $GITHUB_STEP_SUMMARY
302+
fi
303+
else
304+
echo "### ℹ️ Pull Request - Build Only" >> $GITHUB_STEP_SUMMARY
305+
echo "Artifacts are built and tested but not published." >> $GITHUB_STEP_SUMMARY
306+
fi

hyperion/.env.example

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
# mTLS for production, can be false for development
2+
TLS_ENABLED=false
3+
TLS_CERT_PATH=/certs/server.crt
4+
TLS_KEY_PATH=/certs/server.key
5+
TLS_CA_PATH=/certs/ca.crt
6+
17
MODEL_NAME="openai:gpt-4o"
28

39
# For Non-Azure OpenAI

0 commit comments

Comments
 (0)