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
1 change: 1 addition & 0 deletions .bazelrc
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ build --java_language_version=21
build --tool_java_language_version=21
build --java_runtime_version=remotejdk_21
build --tool_java_runtime_version=remotejdk_21
build --define=maven_version=0.0.0-SNAPSHOT

test --test_output=errors
157 changes: 157 additions & 0 deletions .github/workflows/publish-maven.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
name: Publish Maven artifact

on:
workflow_dispatch:
inputs:
tag:
description: Version tag to publish (for example, v1.0.3)
required: true
type: string

permissions:
contents: read

concurrency:
group: publish-maven-${{ inputs.tag }}
cancel-in-progress: false

jobs:
validate:
runs-on: ubuntu-latest
outputs:
tag: ${{ steps.validate.outputs.tag }}
version: ${{ steps.validate.outputs.version }}
steps:
- name: Validate tag
id: validate
env:
RELEASE_TAG: ${{ inputs.tag }}
shell: bash
run: |
set -euo pipefail

if [[ ! "${RELEASE_TAG}" =~ ^v([0-9]+\.[0-9]+\.[0-9]+)$ ]]; then
echo "Tag must match vMAJOR.MINOR.PATCH (for example, v1.0.3)." >&2
exit 1
fi

echo "tag=${RELEASE_TAG}" >> "${GITHUB_OUTPUT}"
echo "version=${BASH_REMATCH[1]}" >> "${GITHUB_OUTPUT}"

publish:
needs: validate
runs-on: ubuntu-latest
environment: maven-publishing
steps:
- name: Check out release tag
uses: actions/checkout@v6
with:
ref: refs/tags/${{ needs.validate.outputs.tag }}
persist-credentials: false

- name: Build Maven artifact
env:
RELEASE_VERSION: ${{ needs.validate.outputs.version }}
run: |
bazel build --define=maven_version="${RELEASE_VERSION}" \
//java/session:session_export \
//java/session:session_export-pom

- name: Verify tag matches Maven version
env:
RELEASE_VERSION: ${{ needs.validate.outputs.version }}
shell: bash
run: |
python3 - <<'PY'
import os
import xml.etree.ElementTree as ET

pom = ET.parse("bazel-bin/java/session/session_export-pom.xml").getroot()
namespace = {"m": "http://maven.apache.org/POM/4.0.0"}
published_version = pom.findtext("m:version", namespaces=namespace)
release_version = os.environ["RELEASE_VERSION"]
if published_version != release_version:
raise SystemExit(
f"Tag version {release_version} does not match Maven version {published_version}"
)
PY

- name: Stage signed Maven artifact
env:
GPG_SIGNING_KEY: ${{ secrets.GPG_SIGNING_KEY }}
GPG_SIGNING_KEY_PASSWORD: ${{ secrets.GPG_SIGNING_KEY_PASSWORD }}
RELEASE_VERSION: ${{ needs.validate.outputs.version }}
USE_IN_MEMORY_PGP_KEYS: "true"
shell: bash
run: |
set -euo pipefail

if [[ -z "${GPG_SIGNING_KEY}" ]]; then
echo "Environment secret GPG_SIGNING_KEY is not configured." >&2
exit 1
fi

staging_repo="${RUNNER_TEMP}/maven-central-staging"
mkdir -p "${staging_repo}"
env \
MAVEN_REPO="file://${staging_repo}" \
PGP_SIGNING_KEY="${GPG_SIGNING_KEY}" \
PGP_SIGNING_PWD="${GPG_SIGNING_KEY_PASSWORD}" \
bazel run --define=maven_version="${RELEASE_VERSION}" \
//java/session:session_export.publish
find "${staging_repo}" -type f -name 'maven-metadata.xml*' -delete

- name: Create Maven Central bundle
shell: bash
run: |
set -euo pipefail

staging_repo="${RUNNER_TEMP}/maven-central-staging"
bundle="${RUNNER_TEMP}/maven-central-bundle.zip"
if [[ -z "$(find "${staging_repo}" -type f -print -quit)" ]]; then
echo "The staged Maven repository is empty." >&2
exit 1
fi
while IFS= read -r artifact; do
if [[ ! -f "${artifact}.asc" ]]; then
echo "Missing signature for ${artifact}" >&2
exit 1
fi
done < <(find "${staging_repo}" -type f \( -name '*.jar' -o -name '*.pom' \))
(
cd "${staging_repo}"
zip -q -r "${bundle}" .
)

- name: Upload deployment to Central Portal
env:
MAVEN_CENTRAL_PASSWORD: ${{ secrets.MAVEN_CENTRAL_PASSWORD }}
MAVEN_CENTRAL_USERNAME: ${{ secrets.MAVEN_CENTRAL_USERNAME }}
RELEASE_VERSION: ${{ needs.validate.outputs.version }}
shell: bash
run: |
set -euo pipefail

if [[ -z "${MAVEN_CENTRAL_USERNAME}" || -z "${MAVEN_CENTRAL_PASSWORD}" ]]; then
echo "Environment secrets MAVEN_CENTRAL_USERNAME and MAVEN_CENTRAL_PASSWORD are not configured." >&2
exit 1
fi

repository_name="${GITHUB_REPOSITORY#*/}"
deployment_name="${repository_name}-${RELEASE_VERSION}"
bundle="${RUNNER_TEMP}/maven-central-bundle.zip"
authorization="$(printf '%s:%s' "${MAVEN_CENTRAL_USERNAME}" "${MAVEN_CENTRAL_PASSWORD}" | base64 -w 0)"
deployment_id="$(curl --fail-with-body --silent --show-error \
--request POST \
--header "Authorization: Bearer ${authorization}" \
--url-query "name=${deployment_name}" \
--url-query "publishingType=USER_MANAGED" \
--form "bundle=@${bundle};type=application/octet-stream" \
"https://central.sonatype.com/api/v1/publisher/upload")"

{
echo "### Maven Central deployment"
echo
echo "- Name: ${deployment_name}"
echo "- ID: ${deployment_id}"
} >> "${GITHUB_STEP_SUMMARY}"
11 changes: 6 additions & 5 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk")
go_sdk.from_file(go_mod = "//:go.mod")

go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps")

go_deps.from_file(go_mod = "//:go.mod")
use_repo(
go_deps,
Expand All @@ -24,16 +23,18 @@ use_repo(
inject_repo(
go_deps,
"rules_go",
"rules_java"
"rules_java",
)

bazel_dep(name = "contrib_rules_jvm", version = "0.32.0")
bazel_dep(name = "contrib_rules_jvm", version = "0.33.0")
bazel_dep(name = "rules_java", version = "9.3.0")
bazel_dep(name = "rules_jvm_external", version = "6.9")
bazel_dep(name = "rules_jvm_external", version = "6.10")

maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven")
maven.install(
artifacts = [
"co.atoms.lib.net.location:location:1.0.3",
"com.google.protobuf:protobuf-java:4.34.1",
"com.google.code.findbugs:jsr305:3.0.2",
"com.google.guava:guava:33.3.1-jre",
"io.grpc:grpc-api:1.72.0",
Expand All @@ -45,10 +46,10 @@ maven.install(
"org.slf4j:slf4j-api:2.0.17",
],
known_contributing_modules = ["protobuf"],
lock_file = "//:maven_install.json",
repositories = [
"https://repo1.maven.org/maven2",
],
lock_file = "//:maven_install.json",
)
use_repo(maven, "maven")

Expand Down
37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,40 @@

Session library provides data types for communication between parties
using sessions.

## Publishing the Java artifact

Build the Maven artifact and its POM:

```shell
bazel build //java/session:session_export //java/session:session_export-pom
```

Ordinary builds use version `0.0.0-SNAPSHOT`. Supply a release version with a
Bazel definition:

```shell
bazel build --define=maven_version=1.0.3 \
//java/session:session_export \
//java/session:session_export-pom
```

Publish to a local Maven repository for testing:

```shell
MAVEN_REPO="file://${HOME}/.m2/repository" \
bazel run --define=maven_version=1.0.3 \
//java/session:session_export.publish
```

For a remote Maven repository, set `MAVEN_REPO`, `MAVEN_USER`, and
`MAVEN_PASSWORD` in the environment before running the same publish target.

### Publishing from GitHub Actions

The `Publish Maven artifact` workflow publishes an existing `vMAJOR.MINOR.PATCH`
tag when started manually from the Actions page. It passes the version from the
tag to Bazel when building the artifact. The workflow creates a signed Maven
repository bundle and uploads it to the Central Publisher Portal as a
user-managed deployment. An authorized person must then review it in the Portal
and either publish it to Maven Central or drop it.
24 changes: 20 additions & 4 deletions java/session/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,28 +1,44 @@
load("@contrib_rules_jvm//java:defs.bzl", "java_junit5_test")
load("@rules_java//java:defs.bzl", "java_library")
load("@rules_jvm_external//:defs.bzl", "maven_export")

MAVEN_COORDINATES = "co.atoms.lib.net.session:session:$(maven_version)"

java_library(
name = "session",
srcs = glob(
["*.java"],
exclude = ["*Test.java"],
),
visibility = ["//:__subpackages__"],
tags = ["maven_coordinates=%s" % MAVEN_COORDINATES],
visibility = ["//visibility:public"],
exports = [
"//proto/atoms/lib/net/session:session_java_proto",
"@com_google_protobuf//java/core",
"@maven//:co_atoms_lib_net_location_location", # keep: published API dependency
"@maven//:com_google_protobuf_protobuf_java",
"@maven//:io_grpc_grpc_stub", # keep: published API dependency
],
deps = [
"//proto/atoms/lib/net/session:session_java_proto",
"@co_atoms_go_lib_net_location//proto/atoms/lib/net/location:location_java_proto",
"@com_google_protobuf//java/core",
"@maven//:co_atoms_lib_net_location_location",
"@maven//:com_google_code_findbugs_jsr305",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
"@maven//:io_grpc_grpc_stub",
"@maven//:org_slf4j_slf4j_api",
],
)

maven_export(
name = "session_export",
excluded_workspaces = {
"gazelle": "@maven//:co_atoms_lib_net_location_location",
},
lib_name = "session",
maven_coordinates = MAVEN_COORDINATES,
pom_template = "pom.xml.tpl",
)

java_junit5_test(
name = "session_test",
srcs = glob([
Expand Down
42 changes: 42 additions & 0 deletions java/session/pom.xml.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>{groupId}</groupId>
<artifactId>{artifactId}</artifactId>
<version>{version}</version>
<packaging>{type}</packaging>

<name>Session Library</name>
<description>Data types for communication between parties using sessions.</description>
<url>https://github.com/atoms-co/session-lib</url>

<licenses>
<license>
<name>Apache License, Version 2.0</name>
<url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
<distribution>repo</distribution>
</license>
</licenses>

<developers>
<developer>
<name>Sergey Tyurin</name>
<email>sergey.tyurin@atoms.co</email>
<organization>Atoms</organization>
<organizationUrl>https://atoms.co</organizationUrl>
</developer>
</developers>

<scm>
<connection>scm:git:https://github.com/atoms-co/session-lib.git</connection>
<developerConnection>scm:git:ssh://git@github.com/atoms-co/session-lib.git</developerConnection>
<url>https://github.com/atoms-co/session-lib</url>
</scm>

<dependencies>
{dependencies}
</dependencies>
</project>
Loading