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
10 changes: 10 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,22 @@ jobs:
java-version: ${{ matrix.java }}
cache: maven

- name: Set up Gradle
if: matrix.java == '17'
uses: gradle/actions/setup-gradle@v6
with:
gradle-version: "9.5.1"

- run: ./mvnw --batch-mode --no-transfer-progress verify

- name: Verify clean BOM consumers
if: matrix.java == '17'
run: ./scripts/verify-consumer.sh

- name: Verify clean Gradle BOM consumers
if: matrix.java == '17'
run: ./scripts/verify-gradle-consumer.sh

- name: Verify Spring Framework 7 compatibility
if: matrix.java == '17'
run: ./mvnw --batch-mode --no-transfer-progress -pl aep-spring-webmvc -am -Pspring7 verify
Expand Down
199 changes: 199 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
name: Release

on:
workflow_dispatch:

concurrency:
group: aep-java-release
cancel-in-progress: false

permissions:
attestations: write
contents: write
id-token: write

jobs:
release:
if: github.repository == 'aep-foundation/aep-java'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0

- name: Validate release
id: release
env:
GH_TOKEN: ${{ github.token }}
run: |
if [[ "$GITHUB_REF" != "refs/heads/main" ]]; then
echo "Releases must run from main." >&2
exit 1
fi
version=$(./mvnw --batch-mode --no-transfer-progress help:evaluate -Dexpression=project.version -DforceStdout -q)
if [[ ! "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "The project version must be a stable semantic version such as 0.1.0." >&2
exit 1
fi
tag="v$version"
if gh release view "$tag" >/dev/null 2>&1; then
echo "Release $tag already exists." >&2
exit 1
fi
if git ls-remote --exit-code --tags origin "refs/tags/$tag" >/dev/null 2>&1; then
tag_commit=$(git rev-list -n 1 "$tag")
if [[ "$tag_commit" != "$GITHUB_SHA" ]]; then
echo "Tag $tag does not identify the selected main commit." >&2
exit 1
fi
fi
echo "tag=$tag" >> "$GITHUB_OUTPUT"
echo "version=$version" >> "$GITHUB_OUTPUT"
artifact="https://repo1.maven.org/maven2/foundation/aep/aep-core/$version/aep-core-$version.pom"
if curl --fail --silent --show-error --head "$artifact" >/dev/null; then
echo "published=true" >> "$GITHUB_OUTPUT"
else
echo "published=false" >> "$GITHUB_OUTPUT"
fi

- name: Check out AEP specifications
uses: actions/checkout@v7
with:
repository: aep-foundation/aep-specs
path: .conformance/aep-specs

- name: Check out Node.js reference implementation
uses: actions/checkout@v7
with:
repository: aep-foundation/aep-node
path: .conformance/aep-node

- uses: ruby/setup-ruby@v1
with:
ruby-version: "3.3"
bundler-cache: true
working-directory: .conformance/aep-specs/ietf

- uses: actions/setup-java@v6
with:
distribution: temurin
java-version: "17"
cache: maven
server-id: central
server-username-env-var: CENTRAL_USERNAME
server-password-env-var: CENTRAL_PASSWORD

- name: Set up Gradle
uses: gradle/actions/setup-gradle@v6
with:
gradle-version: "9.5.1"

- name: Set up pnpm
uses: pnpm/action-setup@v6
with:
version: 11.1.3

- name: Set up Node.js
uses: actions/setup-node@v7
with:
node-version: 24

- name: Install Node.js reference implementation
run: pnpm --dir .conformance/aep-node install --frozen-lockfile

- name: Verify release
run: ./mvnw --batch-mode --no-transfer-progress verify

- name: Verify Spring Framework 7 compatibility
run: ./mvnw --batch-mode --no-transfer-progress -pl aep-spring-webmvc -am -Pspring7 verify

- name: Run shared conformance harness
run: ./scripts/run-conformance.sh
env:
AEP_SPECS_DIR: .conformance/aep-specs

- name: Run Node.js interoperability
run: ./scripts/run-node-interoperability.sh
env:
AEP_NODE_DIR: .conformance/aep-node

- name: Verify clean Maven BOM consumers
run: ./scripts/verify-consumer.sh

- name: Verify clean Gradle BOM consumers
run: ./scripts/verify-gradle-consumer.sh

- name: Inspect release artifacts
run: ./scripts/verify-release-artifacts.sh

- name: Publish Maven artifacts
if: steps.release.outputs.published != 'true'
run: ./mvnw --batch-mode --no-transfer-progress -Prelease -Dgpg.signer=bc deploy
env:
CENTRAL_PASSWORD: ${{ secrets.CENTRAL_PASSWORD }}
CENTRAL_USERNAME: ${{ secrets.CENTRAL_USERNAME }}
MAVEN_GPG_KEY: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }}
MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}

- name: Attest Maven artifacts
uses: actions/attest-build-provenance@v4
with:
subject-path: |
aep-core/target/aep-core-${{ steps.release.outputs.version }}*.jar
aep-json-jackson2/target/aep-json-jackson2-${{ steps.release.outputs.version }}*.jar
aep-json-jackson3/target/aep-json-jackson3-${{ steps.release.outputs.version }}*.jar
aep-agent/target/aep-agent-${{ steps.release.outputs.version }}*.jar
aep-service/target/aep-service-${{ steps.release.outputs.version }}*.jar
aep-httpserver/target/aep-httpserver-${{ steps.release.outputs.version }}*.jar
aep-servlet/target/aep-servlet-${{ steps.release.outputs.version }}*.jar
aep-spring-webmvc/target/aep-spring-webmvc-${{ steps.release.outputs.version }}*.jar
aep-platform/target/aep-platform-${{ steps.release.outputs.version }}*.jar

- name: Wait for Maven Central availability
env:
VERSION: ${{ steps.release.outputs.version }}
run: |
artifact="https://repo1.maven.org/maven2/foundation/aep/aep-core/$VERSION/aep-core-$VERSION.pom"
for attempt in {1..60}; do
if curl --fail --silent --show-error --head "$artifact" >/dev/null; then
exit 0
fi
sleep 10
done
echo "Maven Central did not expose $artifact within 10 minutes." >&2
exit 1

- name: Verify Maven Central consumer
run: ./scripts/verify-consumer.sh
env:
AEP_CONSUMER_SOURCE: central

- name: Verify Maven Central Gradle consumer
run: ./scripts/verify-gradle-consumer.sh
env:
AEP_CONSUMER_SOURCE: central

- name: Create release tag
env:
TAG: ${{ steps.release.outputs.tag }}
run: |
if git rev-parse --verify "refs/tags/$TAG" >/dev/null 2>&1; then
exit 0
fi
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git tag --annotate "$TAG" --message "AEP Java $TAG" "$GITHUB_SHA"
git push origin "$TAG"

- name: Publish GitHub release
run: >-
gh release create "${{ steps.release.outputs.tag }}"
.conformance/reports/agent.json#aep-java-agent-conformance.json
.conformance/reports/service.json#aep-java-service-conformance.json
.conformance/reports/platform.json#aep-java-platform-conformance.json
.interop/reports/aep-java-node-interoperability.json#aep-java-node-interoperability.json
--generate-notes
--title "AEP Java ${{ steps.release.outputs.tag }}"
--verify-tag
env:
GH_TOKEN: ${{ github.token }}
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.DS_Store
.gradle/
.conformance/
.interop/
.idea/
Expand All @@ -8,4 +9,5 @@
.vscode/
target/
**/target/
build/
*.iml
34 changes: 33 additions & 1 deletion DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## Requirements

- Java 17 or newer.
- Gradle 9.5.1 for the Gradle BOM consumer check.
- No system Maven installation; use the checked-in Maven Wrapper.

## Verification
Expand All @@ -12,13 +13,15 @@ Run the complete repository gate before merging:
```sh
./mvnw verify
./scripts/verify-consumer.sh
./scripts/verify-gradle-consumer.sh
```

The Maven gate compiles all modules, runs tests, enforces dependency convergence and formatting,
and runs Checkstyle, PMD, copy-paste detection, SpotBugs, and JaCoCo reporting. The consumer check
installs the reactor into an isolated temporary repository and proves that a project can import
`aep-bom`, omit versions from its AEP module dependencies, and execute the public JSON API with
either Jackson 2 or Jackson 3.
either Jackson 2 or Jackson 3. The Gradle check proves the same combinations through Gradle's
platform support.

Format Java sources with:

Expand Down Expand Up @@ -54,3 +57,32 @@ the other official SDKs as implementation evidence after confirming the specific
All public modules use one lockstep semantic version. `aep-bom` exposes those compatible module
versions to Maven and Gradle consumers without requiring them to inherit the reactor parent.
Examples and conformance tooling remain repository-only modules.

## Releases

The manual `Release` workflow publishes these artifacts to Maven Central:

- `aep-java` parent POM and `aep-bom`;
- `aep-core`, `aep-json-jackson2`, and `aep-json-jackson3`;
- `aep-agent`, `aep-service`, and `aep-platform`;
- `aep-httpserver`, `aep-servlet`, and `aep-spring-webmvc`.

The `examples` and `aep-conformance` modules are excluded from publication. A release requires a
stable semantic version on `main` and these repository Actions secrets:

- `CENTRAL_USERNAME`
- `CENTRAL_PASSWORD`
- `MAVEN_GPG_PRIVATE_KEY`
- `MAVEN_GPG_PASSPHRASE`

Before publishing, the workflow runs the repository gates, Spring Framework 7 verification, shared
conformance, Node.js interoperability, Maven and Gradle BOM consumers, and release artifact
inspection. It publishes and attests the signed artifacts, waits for Maven Central, verifies fresh
Maven and Gradle consumers against Central, creates the matching `vX.Y.Z` tag, and publishes the
GitHub release with its conformance and interoperability reports.

Inspect the release profile locally without uploading anything:

```sh
./scripts/verify-release-artifacts.sh
```
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Agent Enrollment Protocol for Java

[![CI](https://github.com/aep-foundation/aep-java/actions/workflows/ci.yml/badge.svg)](https://github.com/aep-foundation/aep-java/actions/workflows/ci.yml)
[![Maven Central](https://img.shields.io/maven-central/v/foundation.aep/aep-agent)](https://central.sonatype.com/namespace/foundation.aep)
[![Java](https://img.shields.io/badge/Java-17%2B-ED8B00?logo=openjdk&logoColor=white)](https://openjdk.org/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE)

Expand Down
2 changes: 1 addition & 1 deletion aep-agent/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<parent>
<groupId>foundation.aep</groupId>
<artifactId>aep-java</artifactId>
<version>0.1.0-SNAPSHOT</version>
<version>0.1.0</version>
</parent>

<artifactId>aep-agent</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion aep-bom/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<parent>
<groupId>foundation.aep</groupId>
<artifactId>aep-java</artifactId>
<version>0.1.0-SNAPSHOT</version>
<version>0.1.0</version>
</parent>

<artifactId>aep-bom</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion aep-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<parent>
<groupId>foundation.aep</groupId>
<artifactId>aep-java</artifactId>
<version>0.1.0-SNAPSHOT</version>
<version>0.1.0</version>
</parent>

<artifactId>aep-core</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion aep-httpserver/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<parent>
<groupId>foundation.aep</groupId>
<artifactId>aep-java</artifactId>
<version>0.1.0-SNAPSHOT</version>
<version>0.1.0</version>
</parent>

<artifactId>aep-httpserver</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion aep-json-jackson2/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<parent>
<groupId>foundation.aep</groupId>
<artifactId>aep-java</artifactId>
<version>0.1.0-SNAPSHOT</version>
<version>0.1.0</version>
</parent>

<artifactId>aep-json-jackson2</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion aep-json-jackson3/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<parent>
<groupId>foundation.aep</groupId>
<artifactId>aep-java</artifactId>
<version>0.1.0-SNAPSHOT</version>
<version>0.1.0</version>
</parent>

<artifactId>aep-json-jackson3</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion aep-platform/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<parent>
<groupId>foundation.aep</groupId>
<artifactId>aep-java</artifactId>
<version>0.1.0-SNAPSHOT</version>
<version>0.1.0</version>
</parent>

<artifactId>aep-platform</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion aep-service/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<parent>
<groupId>foundation.aep</groupId>
<artifactId>aep-java</artifactId>
<version>0.1.0-SNAPSHOT</version>
<version>0.1.0</version>
</parent>

<artifactId>aep-service</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion aep-servlet/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<parent>
<groupId>foundation.aep</groupId>
<artifactId>aep-java</artifactId>
<version>0.1.0-SNAPSHOT</version>
<version>0.1.0</version>
</parent>

<artifactId>aep-servlet</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion aep-spring-webmvc/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<parent>
<groupId>foundation.aep</groupId>
<artifactId>aep-java</artifactId>
<version>0.1.0-SNAPSHOT</version>
<version>0.1.0</version>
</parent>

<artifactId>aep-spring-webmvc</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion examples/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<parent>
<groupId>foundation.aep</groupId>
<artifactId>aep-java</artifactId>
<version>0.1.0-SNAPSHOT</version>
<version>0.1.0</version>
</parent>

<artifactId>aep-examples</artifactId>
Expand Down
Loading