This is an automated email from the ASF dual-hosted git repository.
JingsongLi pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/paimon-mosaic.git
The following commit(s) were added to refs/heads/main by this push:
new 1abf5b5 Add release documentation and rename crates/packages with
paimon prefix (#26)
1abf5b5 is described below
commit 1abf5b5e8b3eaf5a315945a3049820848ca14dd8
Author: Jingsong Lee <[email protected]>
AuthorDate: Thu May 21 13:41:31 2026 +0800
Add release documentation and rename crates/packages with paimon prefix
(#26)
- Add release docs as HTML pages (creating-a-release,
verifying-a-release-candidate, releases)
- Rename crates: mosaic-core -> paimon-mosaic-core, mosaic-ffi ->
paimon-mosaic-ffi, mosaic-jni -> paimon-mosaic-jni
- Rename Python package: mosaic-format -> paimon-mosaic
- Update all workflows, docs, source code, and .gitignore for new library
names
- Improve create_source_release.sh with usage header, trap fix, and
verification steps
- Update doc titles from "Mosaic" to "Paimon Mosaic"
---
.github/workflows/ci.yml | 8 +-
.github/workflows/publish_snapshot.yml | 10 +-
.github/workflows/release-java.yml | 10 +-
.github/workflows/release-python.yml | 37 ++-
.github/workflows/release-rust.yml | 8 +-
.gitignore | 4 +-
core/Cargo.toml | 2 +-
core/tests/robustness_test.rs | 14 +-
core/tests/stress_test.rs | 6 +-
cpp/CMakeLists.txt | 8 +-
docs/README.md | 17 +-
docs/cpp-api.html | 13 +-
docs/creating-a-release.html | 352 +++++++++++++++++++++
docs/design.html | 5 +-
docs/index.html | 5 +-
docs/java-api.html | 13 +-
docs/python-api.html | 9 +-
docs/releases.html | 98 ++++++
docs/verifying-a-release-candidate.html | 196 ++++++++++++
ffi/Cargo.toml | 4 +-
.../java/org/apache/paimon/mosaic/NativeLib.java | 10 +-
jni/Cargo.toml | 4 +-
python/mosaic/_ffi.py | 8 +-
python/pyproject.toml | 4 +-
python/setup.py | 6 +-
tools/releasing/create_source_release.sh | 21 +-
tools/releasing/update_branch_version.sh | 11 +-
27 files changed, 791 insertions(+), 92 deletions(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index c389704..5f81ac2 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -90,12 +90,12 @@ jobs:
sudo apt-get install -y libarrow-dev
- name: Build FFI library
- run: cargo build --release -p mosaic-ffi
+ run: cargo build --release -p paimon-mosaic-ffi
- name: Build C++ test
run: |
cmake -S cpp -B cpp/build \
- -DMOSAIC_FFI_LIB=${{ github.workspace
}}/target/release/libmosaic_ffi.so
+ -DMOSAIC_FFI_LIB=${{ github.workspace
}}/target/release/libpaimon_mosaic_ffi.so
cmake --build cpp/build
- name: Run C++ test
@@ -126,7 +126,7 @@ jobs:
distribution: 'temurin'
- name: Build JNI library
- run: cargo build -p mosaic-jni --release
+ run: cargo build -p paimon-mosaic-jni --release
- name: Run Java tests
working-directory: java
@@ -154,7 +154,7 @@ jobs:
python-version: '3.12'
- name: Build FFI library
- run: cargo build --release -p mosaic-ffi
+ run: cargo build --release -p paimon-mosaic-ffi
- name: Install Python dependencies
working-directory: python
diff --git a/.github/workflows/publish_snapshot.yml
b/.github/workflows/publish_snapshot.yml
index 979910a..cb2c5ad 100644
--- a/.github/workflows/publish_snapshot.yml
+++ b/.github/workflows/publish_snapshot.yml
@@ -42,22 +42,22 @@ jobs:
target: x86_64-unknown-linux-gnu
os_name: linux
arch: x86_64
- lib_name: libmosaic_jni.so
+ lib_name: libpaimon_mosaic_jni.so
- os: ubuntu-24.04-arm
target: aarch64-unknown-linux-gnu
os_name: linux
arch: aarch64
- lib_name: libmosaic_jni.so
+ lib_name: libpaimon_mosaic_jni.so
- os: macos-latest
target: aarch64-apple-darwin
os_name: macos
arch: aarch64
- lib_name: libmosaic_jni.dylib
+ lib_name: libpaimon_mosaic_jni.dylib
- os: windows-latest
target: x86_64-pc-windows-msvc
os_name: windows
arch: x86_64
- lib_name: mosaic_jni.dll
+ lib_name: paimon_mosaic_jni.dll
steps:
- uses: actions/checkout@v4
@@ -78,7 +78,7 @@ jobs:
${{ runner.os }}-${{ matrix.target }}-cargo-
- name: Build JNI library
- run: cargo build --release -p mosaic-jni
+ run: cargo build --release -p paimon-mosaic-jni
- name: Upload native library
uses: actions/upload-artifact@v4
diff --git a/.github/workflows/release-java.yml
b/.github/workflows/release-java.yml
index 433d69e..423f368 100644
--- a/.github/workflows/release-java.yml
+++ b/.github/workflows/release-java.yml
@@ -43,22 +43,22 @@ jobs:
target: x86_64-unknown-linux-gnu
os_name: linux
arch: x86_64
- lib_name: libmosaic_jni.so
+ lib_name: libpaimon_mosaic_jni.so
- os: ubuntu-24.04-arm
target: aarch64-unknown-linux-gnu
os_name: linux
arch: aarch64
- lib_name: libmosaic_jni.so
+ lib_name: libpaimon_mosaic_jni.so
- os: macos-latest
target: aarch64-apple-darwin
os_name: macos
arch: aarch64
- lib_name: libmosaic_jni.dylib
+ lib_name: libpaimon_mosaic_jni.dylib
- os: windows-latest
target: x86_64-pc-windows-msvc
os_name: windows
arch: x86_64
- lib_name: mosaic_jni.dll
+ lib_name: paimon_mosaic_jni.dll
steps:
- uses: actions/checkout@v4
@@ -68,7 +68,7 @@ jobs:
rustup default stable
- name: Build JNI library
- run: cargo build --release -p mosaic-jni
+ run: cargo build --release -p paimon-mosaic-jni
- name: Upload native library
uses: actions/upload-artifact@v4
diff --git a/.github/workflows/release-python.yml
b/.github/workflows/release-python.yml
index 1c7a184..4c24155 100644
--- a/.github/workflows/release-python.yml
+++ b/.github/workflows/release-python.yml
@@ -15,7 +15,7 @@
# specific language governing permissions and limitations
# under the License.
-# Publish the mosaic-format Python package to PyPI.
+# Publish the paimon-mosaic Python package to PyPI.
#
# Trigger: push a version tag (e.g. v0.1.0, v0.1.0-rc1).
# Pre-release tags (containing '-') publish to TestPyPI; release tags publish
to PyPI.
@@ -52,6 +52,14 @@ jobs:
steps:
- uses: actions/checkout@v4
+ - name: Inject RC version into pyproject.toml
+ if: contains(github.ref, '-rc')
+ run: |
+ TAG="${GITHUB_REF#refs/tags/v}"
+ # Convert 0.1.0-rc1 to PEP 440: 0.1.0rc1
+ PEP440_VERSION=$(echo "$TAG" | sed 's/-rc/rc/')
+ sed -i "s/^version = .*/version = \"${PEP440_VERSION}\"/"
python/pyproject.toml
+
- name: Set up Python
uses: actions/setup-python@v5
with:
@@ -69,8 +77,8 @@ jobs:
CIBW_BEFORE_ALL_LINUX: >
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s
-- -y &&
source $HOME/.cargo/env &&
- cargo build --release -p mosaic-ffi &&
- cp target/release/libmosaic_ffi.so {package}/mosaic/
+ cargo build --release -p paimon-mosaic-ffi &&
+ cp target/release/libpaimon_mosaic_ffi.so {package}/mosaic/
- name: Upload wheels
uses: actions/upload-artifact@v4
@@ -86,17 +94,24 @@ jobs:
include:
- os: macos-latest
target: aarch64-apple-darwin
- lib_name: libmosaic_ffi.dylib
+ lib_name: libpaimon_mosaic_ffi.dylib
steps:
- uses: actions/checkout@v4
+ - name: Inject RC version into pyproject.toml
+ if: contains(github.ref, '-rc')
+ run: |
+ TAG="${GITHUB_REF#refs/tags/v}"
+ PEP440_VERSION=$(echo "$TAG" | sed 's/-rc/rc/')
+ sed -i '' "s/^version = .*/version = \"${PEP440_VERSION}\"/"
python/pyproject.toml
+
- name: Setup Rust toolchain
run: |
rustup update stable
rustup default stable
- name: Build native library
- run: cargo build --release -p mosaic-ffi
+ run: cargo build --release -p paimon-mosaic-ffi
- name: Copy native library into package
run: cp target/release/${{ matrix.lib_name }} python/mosaic/
@@ -130,17 +145,25 @@ jobs:
steps:
- uses: actions/checkout@v4
+ - name: Inject RC version into pyproject.toml
+ if: contains(github.ref, '-rc')
+ shell: bash
+ run: |
+ TAG="${GITHUB_REF#refs/tags/v}"
+ PEP440_VERSION=$(echo "$TAG" | sed 's/-rc/rc/')
+ sed -i "s/^version = .*/version = \"${PEP440_VERSION}\"/"
python/pyproject.toml
+
- name: Setup Rust toolchain
run: |
rustup update stable
rustup default stable
- name: Build native library
- run: cargo build --release -p mosaic-ffi
+ run: cargo build --release -p paimon-mosaic-ffi
- name: Copy native library into package
shell: bash
- run: cp target/release/mosaic_ffi.dll python/mosaic/
+ run: cp target/release/paimon_mosaic_ffi.dll python/mosaic/
- name: Set up Python
uses: actions/setup-python@v5
diff --git a/.github/workflows/release-rust.yml
b/.github/workflows/release-rust.yml
index 13d8331..7585019 100644
--- a/.github/workflows/release-rust.yml
+++ b/.github/workflows/release-rust.yml
@@ -15,7 +15,7 @@
# specific language governing permissions and limitations
# under the License.
-# Publish mosaic-core crate to crates.io.
+# Publish paimon-mosaic-core crate to crates.io.
#
# Trigger: push a version tag (e.g. v0.1.0, v0.1.0-rc1).
# Pre-release tags (containing '-') only run dry-run checks without publishing.
@@ -45,10 +45,10 @@ jobs:
rustup default stable
- name: Dry run
- run: cargo publish -p mosaic-core --dry-run
+ run: cargo publish -p paimon-mosaic-core --dry-run
- - name: Publish mosaic-core to crates.io
+ - name: Publish paimon-mosaic-core to crates.io
if: startsWith(github.ref, 'refs/tags/') && !contains(github.ref, '-')
- run: cargo publish -p mosaic-core
+ run: cargo publish -p paimon-mosaic-core
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
diff --git a/.gitignore b/.gitignore
index f0b6b17..6f4017e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -34,8 +34,8 @@ __pycache__/
python/dist/
python/build/
.pytest_cache/
-python/mosaic/libmosaic_ffi.*
-python/mosaic/mosaic_ffi.dll
+python/mosaic/libpaimon_mosaic_ffi.*
+python/mosaic/paimon_mosaic_ffi.dll
# IDE
.idea/
diff --git a/core/Cargo.toml b/core/Cargo.toml
index f4e4246..c59c1a4 100644
--- a/core/Cargo.toml
+++ b/core/Cargo.toml
@@ -16,7 +16,7 @@
# under the License.
[package]
-name = "mosaic-core"
+name = "paimon-mosaic-core"
version = "0.1.0"
edition = "2021"
description = "Mosaic file format — core Rust library"
diff --git a/core/tests/robustness_test.rs b/core/tests/robustness_test.rs
index 08e5a27..1c051a0 100644
--- a/core/tests/robustness_test.rs
+++ b/core/tests/robustness_test.rs
@@ -31,9 +31,9 @@ use std::sync::Arc;
use arrow_array::*;
use arrow_schema::{DataType, Field, Schema, TimeUnit};
-use mosaic_core::reader::{InputFile, MosaicReader, ReaderAccess};
-use mosaic_core::spec;
-use mosaic_core::writer::{MosaicWriter, OutputFile, WriterOptions};
+use paimon_mosaic_core::reader::{InputFile, MosaicReader, ReaderAccess};
+use paimon_mosaic_core::spec;
+use paimon_mosaic_core::writer::{MosaicWriter, OutputFile, WriterOptions};
// ======================== Test Infrastructure ========================
@@ -1717,7 +1717,7 @@ fn test_timestamp_nanos_basic_roundtrip() {
assert!(!col.is_null(i));
assert_eq!(
col.value(i),
- mosaic_core::types::millis_nanos_to_ns(
+ paimon_mosaic_core::types::millis_nanos_to_ns(
1_700_000_000_000i64 + i as i64,
(i % 1_000_000) as i32,
)
@@ -1745,14 +1745,14 @@ fn test_timestamp_nanos_extreme_values() {
0,
i64::MAX,
i64::MIN,
- mosaic_core::types::millis_nanos_to_ns(1_700_000_000_000,
999_999).unwrap(),
- mosaic_core::types::millis_nanos_to_ns(-1_700_000_000_000, 1).unwrap(),
+ paimon_mosaic_core::types::millis_nanos_to_ns(1_700_000_000_000,
999_999).unwrap(),
+ paimon_mosaic_core::types::millis_nanos_to_ns(-1_700_000_000_000,
1).unwrap(),
1,
-1,
];
let (millis_data, nanos_data): (Vec<i64>, Vec<i32>) = ns_data
.iter()
- .map(|&ns| mosaic_core::types::ns_to_millis_nanos(ns))
+ .map(|&ns| paimon_mosaic_core::types::ns_to_millis_nanos(ns))
.unzip();
let millis_arr = Int64Array::from(millis_data.clone());
diff --git a/core/tests/stress_test.rs b/core/tests/stress_test.rs
index 37d0289..8aef43c 100644
--- a/core/tests/stress_test.rs
+++ b/core/tests/stress_test.rs
@@ -28,8 +28,8 @@ use std::sync::Arc;
use arrow_array::*;
use arrow_schema::{DataType, Field, Schema, TimeUnit};
-use mosaic_core::reader::{InputFile, MosaicReader, ReaderAccess};
-use mosaic_core::writer::{MosaicWriter, OutputFile, WriterOptions};
+use paimon_mosaic_core::reader::{InputFile, MosaicReader, ReaderAccess};
+use paimon_mosaic_core::writer::{MosaicWriter, OutputFile, WriterOptions};
struct MemOutputFile {
pub buf: Vec<u8>,
@@ -483,7 +483,7 @@ fn test_all_types_at_scale() {
} else {
let millis = 1_700_000_000_000i64 + (batch_start + i) as
i64;
let nanos = ((batch_start + i) % 1_000_000) as i32;
- Some(mosaic_core::types::millis_nanos_to_ns(millis,
nanos).unwrap())
+ Some(paimon_mosaic_core::types::millis_nanos_to_ns(millis,
nanos).unwrap())
}
})
.collect();
diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt
index 6e69fcb..9cfcb11 100644
--- a/cpp/CMakeLists.txt
+++ b/cpp/CMakeLists.txt
@@ -23,14 +23,14 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(Arrow REQUIRED)
-set(MOSAIC_FFI_LIB "" CACHE FILEPATH "Path to libmosaic_ffi shared library")
+set(MOSAIC_FFI_LIB "" CACHE FILEPATH "Path to libpaimon_mosaic_ffi shared
library")
if(NOT MOSAIC_FFI_LIB)
if(APPLE)
- set(MOSAIC_FFI_LIB
"${CMAKE_SOURCE_DIR}/../target/release/libmosaic_ffi.dylib")
+ set(MOSAIC_FFI_LIB
"${CMAKE_SOURCE_DIR}/../target/release/libpaimon_mosaic_ffi.dylib")
elseif(WIN32)
- set(MOSAIC_FFI_LIB
"${CMAKE_SOURCE_DIR}/../target/release/mosaic_ffi.dll")
+ set(MOSAIC_FFI_LIB
"${CMAKE_SOURCE_DIR}/../target/release/paimon_mosaic_ffi.dll")
else()
- set(MOSAIC_FFI_LIB
"${CMAKE_SOURCE_DIR}/../target/release/libmosaic_ffi.so")
+ set(MOSAIC_FFI_LIB
"${CMAKE_SOURCE_DIR}/../target/release/libpaimon_mosaic_ffi.so")
endif()
endif()
diff --git a/docs/README.md b/docs/README.md
index 5df48b6..bf1d9c1 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -40,15 +40,18 @@ Then open http://localhost:8090 in your browser.
```
docs/
-├── index.html # Home page (overview, benchmarks, types)
-├── design.html # Format specification & binary layout
-├── java-api.html # Java API guide
-├── python-api.html # Python API guide
-├── cpp-api.html # C++ API guide
+├── index.html # Home page (overview, benchmarks, types)
+├── design.html # Format specification & binary layout
+├── java-api.html # Java API guide
+├── python-api.html # Python API guide
+├── cpp-api.html # C++ API guide
+├── releases.html # Release listing & download links
+├── creating-a-release.html # Release Manager guide
+├── verifying-a-release-candidate.html # Verification guide for voters
├── css/
-│ └── style.css # Styles (light/dark theme)
+│ └── style.css # Styles (light/dark theme)
└── js/
- └── main.js # Theme toggle & mobile menu
+ └── main.js # Theme toggle & mobile menu
```
## No Build Step Required
diff --git a/docs/cpp-api.html b/docs/cpp-api.html
index f19b099..9b3fa4c 100644
--- a/docs/cpp-api.html
+++ b/docs/cpp-api.html
@@ -22,7 +22,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>C++ API - Mosaic</title>
+ <title>C++ API - Paimon Mosaic</title>
<link rel="stylesheet" href="css/style.css">
<script src="js/main.js"></script>
</head>
@@ -32,7 +32,7 @@
<aside class="sidebar">
<div class="sidebar-header">
- <h2>Mosaic</h2>
+ <h2>Paimon Mosaic</h2>
<p>Columnar-bucket hybrid format</p>
</div>
<nav>
@@ -42,6 +42,7 @@
<li><a href="java-api.html">Java API</a></li>
<li><a href="python-api.html">Python API</a></li>
<li><a href="cpp-api.html">C++ API</a></li>
+ <li><a href="releases.html">Releases</a></li>
</ul>
</nav>
<div class="sidebar-footer">
@@ -56,14 +57,14 @@
<h2>Overview</h2>
<p>
- The <code>ffi/</code> crate generates a shared library
(<code>libmosaic_ffi</code>) and a
+ The <code>ffi/</code> crate generates a shared library
(<code>libpaimon_mosaic_ffi</code>) and a
C header (<code>mosaic.h</code>) via <a
href="https://github.com/mozilla/cbindgen">cbindgen</a>.
The C++ header (<code>mosaic.hpp</code>) is a hand-written
RAII wrapper on top of the C API.
</p>
<h2>Building</h2>
<pre><code><span class="cmt"># Build the FFI shared library</span>
-cargo build --release -p mosaic-ffi
+cargo build --release -p paimon-mosaic-ffi
<span class="cmt"># C header generated at include/mosaic.h</span>
<span class="cmt"># C++ RAII wrapper: include/mosaic.hpp (checked in, not
generated)</span></code></pre>
@@ -72,11 +73,11 @@ cargo build --release -p mosaic-ffi
<p>Link against the shared library and include the appropriate
header:</p>
<pre><code><span class="cmt"># macOS</span>
g++ -std=c++17 -I include/ example.cpp \
- -L target/release -lmosaic_ffi -o example
+ -L target/release -lpaimon_mosaic_ffi -o example
<span class="cmt"># Linux</span>
g++ -std=c++17 -I include/ example.cpp \
- -L target/release -lmosaic_ffi -Wl,-rpath,target/release -o
example</code></pre>
+ -L target/release -lpaimon_mosaic_ffi -Wl,-rpath,target/release -o
example</code></pre>
<h2>Writing (C++)</h2>
<p>
diff --git a/docs/creating-a-release.html b/docs/creating-a-release.html
new file mode 100644
index 0000000..c3d06c7
--- /dev/null
+++ b/docs/creating-a-release.html
@@ -0,0 +1,352 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>Creating a Release - Paimon Mosaic</title>
+ <link rel="stylesheet" href="css/style.css">
+ <script src="js/main.js"></script>
+</head>
+<body>
+ <button class="menu-toggle" aria-label="Menu">☰</button>
+ <div class="overlay"></div>
+
+ <aside class="sidebar">
+ <div class="sidebar-header">
+ <h2>Paimon Mosaic</h2>
+ <p>Columnar-bucket hybrid format</p>
+ </div>
+ <nav>
+ <ul>
+ <li><a href="index.html">Home</a></li>
+ <li><a href="design.html">Design</a></li>
+ <li><a href="java-api.html">Java API</a></li>
+ <li><a href="python-api.html">Python API</a></li>
+ <li><a href="cpp-api.html">C++ API</a></li>
+ <li><a href="releases.html">Releases</a></li>
+ </ul>
+ </nav>
+ <div class="sidebar-footer">
+ <button class="theme-toggle">Dark Mode</button>
+ </div>
+ </aside>
+
+ <main class="main">
+ <div class="content">
+ <h1>Creating a Release</h1>
+ <p class="subtitle">Guide for Release Managers of Apache Paimon
Mosaic, following <a
href="https://www.apache.org/legal/release-policy.html">ASF Release
Policy</a>.</p>
+
+ <!-- ============================================================
-->
+ <h2>Overview</h2>
+ <p>The release process consists of:</p>
+ <ol>
+ <li><a href="#decide-to-release">Decide to release</a></li>
+ <li><a href="#prepare-for-the-release">Prepare for the
release</a></li>
+ <li><a href="#build-a-release-candidate">Build a release
candidate</a></li>
+ <li><a href="#vote-on-the-release-candidate">Vote on the
release candidate</a></li>
+ <li><a href="#fix-any-issues">If necessary, fix any issues and
go back to step 3</a></li>
+ <li><a href="#finalize-the-release">Finalize the
release</a></li>
+ <li><a href="#promote-the-release">Promote the release</a></li>
+ </ol>
+
+ <h3>Automated Publishing</h3>
+ <p>When a version tag is pushed, GitHub Actions automatically
publishes language-specific artifacts:</p>
+ <table>
+ <thead>
+ <tr><th>Component</th><th>Tag Pattern</th><th>Published
To</th><th>Pre-release (<code>-rc</code>) Behavior</th></tr>
+ </thead>
+ <tbody>
+ <tr><td>Rust
crate</td><td><code>v0.1.0</code></td><td>crates.io</td><td>Dry-run
only</td></tr>
+ <tr><td>Java
binding</td><td><code>v0.1.0</code></td><td>Apache Nexus
staging</td><td>Deploys to staging</td></tr>
+ <tr><td>Python
binding</td><td><code>v0.1.0</code></td><td>PyPI</td><td>Publishes to
TestPyPI</td></tr>
+ </tbody>
+ </table>
+ <p>The Release Manager's primary responsibility is managing the
<strong>source release</strong> (tarball + signature) and coordinating the
community vote. Language artifact publishing is handled by CI once the tag is
pushed.</p>
+
+ <!-- ============================================================
-->
+ <h2 id="decide-to-release">Decide to Release</h2>
+ <p>Anybody can propose a release on the dev <a
href="https://lists.apache.org/[email protected]">mailing
list</a>, giving a short rationale and nominating a committer as Release
Manager (including themselves).</p>
+ <p><strong>Checklist:</strong></p>
+ <ul>
+ <li>Community agrees to release</li>
+ <li>A Release Manager is selected</li>
+ </ul>
+
+ <!-- ============================================================
-->
+ <h2 id="prepare-for-the-release">Prepare for the Release</h2>
+
+ <h3>One-time Release Manager Setup</h3>
+
+ <h4>GPG Key</h4>
+ <ol>
+ <li>
+ <p>Install GnuPG:</p>
+<pre><code># macOS
+brew install gnupg
+
+# Ubuntu / Debian
+sudo apt install gnupg2</code></pre>
+ </li>
+ <li>
+ <p>Generate a key pair (RSA 4096, does not expire, use
your <code>@apache.org</code> email):</p>
+<pre><code>gpg --full-gen-key</code></pre>
+ </li>
+ <li>
+ <p>Find your key ID:</p>
+<pre><code>gpg --list-keys --keyid-format short</code></pre>
+ </li>
+ <li>
+ <p>Upload to key server:</p>
+<pre><code>gpg --keyserver hkps://keyserver.ubuntu.com --send-keys
<YOUR_KEY_ID></code></pre>
+ </li>
+ <li>
+ <p>Append to the project <a
href="https://downloads.apache.org/paimon/KEYS">KEYS</a> file:</p>
+<pre><code>svn co https://dist.apache.org/repos/dist/release/paimon/
paimon-dist-release --depth=files
+cd paimon-dist-release
+(gpg --list-sigs <YOUR_KEY_ID> && gpg --armor --export
<YOUR_KEY_ID>) >> KEYS
+svn ci -m "Add <YOUR_NAME>'s public key"</code></pre>
+ </li>
+ <li>
+ <p>Configure Git to sign tags:</p>
+<pre><code>git config --global user.signingkey <YOUR_KEY_ID></code></pre>
+ </li>
+ </ol>
+
+ <h4>GitHub Actions Secrets</h4>
+ <p>Ensure the following repository secrets are configured:</p>
+ <table>
+ <thead>
+ <tr><th>Secret</th><th>Purpose</th></tr>
+ </thead>
+ <tbody>
+
<tr><td><code>CARGO_REGISTRY_TOKEN</code></td><td>crates.io publishing</td></tr>
+
<tr><td><code>NEXUS_STAGE_DEPLOYER_USER</code></td><td>Apache Nexus
staging</td></tr>
+
<tr><td><code>NEXUS_STAGE_DEPLOYER_PW</code></td><td>Apache Nexus
staging</td></tr>
+ <tr><td><code>GPG_SECRET_KEY</code></td><td>Java artifact
signing</td></tr>
+ <tr><td><code>GPG_PASSPHRASE</code></td><td>Java artifact
signing</td></tr>
+ <tr><td><code>PYPI_API_TOKEN</code></td><td>PyPI
publishing</td></tr>
+ <tr><td><code>TEST_PYPI_API_TOKEN</code></td><td>TestPyPI
publishing</td></tr>
+ </tbody>
+ </table>
+
+ <h3>Clone into a Fresh Workspace</h3>
+<pre><code>git clone https://github.com/apache/paimon-mosaic.git
+cd paimon-mosaic</code></pre>
+
+ <h3>Set Up Environment Variables</h3>
+<pre><code>RELEASE_VERSION="0.1.0"
+NEXT_VERSION="0.2.0"
+RC_NUM="1"</code></pre>
+
+ <h3>Create a Release Branch</h3>
+<pre><code>cd tools
+RELEASE_VERSION=${RELEASE_VERSION} RELEASE_CANDIDATE=${RC_NUM}
./releasing/create_release_branch.sh</code></pre>
+ <p>This creates a branch named
<code>release-${RELEASE_VERSION}-rc${RC_NUM}</code> from the current HEAD.</p>
+
+ <h3>Bump Version on Main</h3>
+ <p>After cutting the release branch, bump <code>main</code> to the
next development version:</p>
+<pre><code>git checkout main
+cd tools
+OLD_VERSION=${RELEASE_VERSION} NEW_VERSION=${NEXT_VERSION}-SNAPSHOT
./releasing/update_branch_version.sh</code></pre>
+ <p>The script updates version strings in all <code>pom.xml</code>
(matching both <code>${OLD_VERSION}</code> and
<code>${OLD_VERSION}-SNAPSHOT</code>), <code>Cargo.toml</code> (excluding
<code>target/</code>), and <code>python/pyproject.toml</code> files, then
creates a commit.</p>
+
+ <!-- ============================================================
-->
+ <h2 id="build-a-release-candidate">Build a Release Candidate</h2>
+
+ <h3>Update Versions on the Release Branch</h3>
+ <p>Before tagging, update the release branch to non-SNAPSHOT
versions (removing <code>-SNAPSHOT</code> from <code>pom.xml</code>):</p>
+<pre><code>git checkout release-${RELEASE_VERSION}-rc${RC_NUM}
+cd tools
+OLD_VERSION=${RELEASE_VERSION}-SNAPSHOT NEW_VERSION=${RELEASE_VERSION}
./releasing/update_branch_version.sh
+cd ..</code></pre>
+ <p>This ensures the Java artifacts deployed from the RC tag carry
the final release version (e.g. <code>0.1.0</code>) rather than a SNAPSHOT
suffix.</p>
+
+ <h3>Create the RC Tag</h3>
+ <p>Push a signed RC tag to trigger CI workflows:</p>
+<pre><code>git tag -s v${RELEASE_VERSION}-rc${RC_NUM} -m
"v${RELEASE_VERSION}-rc${RC_NUM}"
+git push origin release-${RELEASE_VERSION}-rc${RC_NUM}
+git push origin v${RELEASE_VERSION}-rc${RC_NUM}</code></pre>
+ <p>After pushing, verify in <a
href="https://github.com/apache/paimon-mosaic/actions">GitHub Actions</a> that
all release workflows succeed:</p>
+ <ul>
+ <li><strong>Release Rust</strong> — dry-run check (does
not publish for RC tags)</li>
+ <li><strong>Release Java</strong> — builds native JNI
libraries for 4 platforms, deploys JAR to Apache Nexus staging</li>
+ <li><strong>Release Python</strong> — builds wheels for
4 platforms, publishes to TestPyPI</li>
+ </ul>
+
+ <h3>Create Source Release Artifacts</h3>
+<pre><code>cd tools
+RELEASE_VERSION=${RELEASE_VERSION}
./releasing/create_source_release.sh</code></pre>
+ <p>This creates the following under
<code>tools/release/</code>:</p>
+ <ul>
+
<li><code>apache-paimon-mosaic-${RELEASE_VERSION}-src.tgz</code> — source
archive</li>
+
<li><code>apache-paimon-mosaic-${RELEASE_VERSION}-src.tgz.asc</code> —
GPG signature</li>
+
<li><code>apache-paimon-mosaic-${RELEASE_VERSION}-src.tgz.sha512</code> —
SHA-512 checksum</li>
+ </ul>
+
+ <h3>Stage Artifacts to SVN</h3>
+<pre><code>svn checkout https://dist.apache.org/repos/dist/dev/paimon/
paimon-dist-dev --depth=immediates
+cd paimon-dist-dev
+mkdir paimon-mosaic-${RELEASE_VERSION}-rc${RC_NUM}
+cp
../paimon-mosaic/tools/release/apache-paimon-mosaic-${RELEASE_VERSION}-src.* \
+ paimon-mosaic-${RELEASE_VERSION}-rc${RC_NUM}/
+svn add paimon-mosaic-${RELEASE_VERSION}-rc${RC_NUM}
+svn commit -m "Add paimon-mosaic ${RELEASE_VERSION} RC${RC_NUM}"</code></pre>
+
+ <p><strong>Checklist:</strong></p>
+ <ul>
+ <li>RC tag pushed and CI workflows succeeded</li>
+ <li>Source tarball, signature, and checksum staged to <a
href="https://dist.apache.org/repos/dist/dev/paimon/">dist.apache.org
dev</a></li>
+ <li>Java artifacts deployed to Nexus staging repository</li>
+ <li>Python wheels published to TestPyPI</li>
+ </ul>
+
+ <!-- ============================================================
-->
+ <h2 id="vote-on-the-release-candidate">Vote on the Release
Candidate</h2>
+ <p>Start a vote on the dev mailing list.</p>
+ <p><strong>Subject:</strong> <code>[VOTE] Release Apache Paimon
Mosaic ${RELEASE_VERSION} (RC${RC_NUM})</code></p>
+<pre><code>Hi everyone,
+
+Please review and vote on release candidate #${RC_NUM} for Apache Paimon
Mosaic ${RELEASE_VERSION}.
+
+[ ] +1 Approve the release
+[ ] +0 No opinion
+[ ] -1 Do not approve (please provide specific comments)
+
+The release candidate is available at:
+https://dist.apache.org/repos/dist/dev/paimon/paimon-mosaic-${RELEASE_VERSION}-rc${RC_NUM}/
+
+Git tag:
+https://github.com/apache/paimon-mosaic/releases/tag/v${RELEASE_VERSION}-rc${RC_NUM}
+
+KEYS for signature verification:
+https://downloads.apache.org/paimon/KEYS
+
+Java artifacts (Nexus staging):
+https://repository.apache.org/content/repositories/orgapachepaimon-XXXX/
+
+Python wheels (TestPyPI):
+https://test.pypi.org/project/paimon-mosaic/${RELEASE_VERSION}rc${RC_NUM}/
+
+Verification guide:
+https://github.com/apache/paimon-mosaic/blob/main/docs/verifying-a-release-candidate.html
+
+The vote will be open for at least 72 hours.
+
+Thanks,
+Release Manager</code></pre>
+ <p>After the vote passes, send a result email with subject:
<code>[RESULT][VOTE] Release Apache Paimon Mosaic ${RELEASE_VERSION}
(RC${RC_NUM})</code></p>
+
+ <!-- ============================================================
-->
+ <h2 id="fix-any-issues">Fix Any Issues</h2>
+ <p>If the vote reveals issues:</p>
+ <ol>
+ <li>Fix them on the release branch via normal PRs.</li>
+ <li>Remove the old RC from dist dev (optional):
+<pre><code>cd paimon-dist-dev
+svn remove paimon-mosaic-${RELEASE_VERSION}-rc${RC_NUM}
+svn commit -m "Remove paimon-mosaic ${RELEASE_VERSION} RC${RC_NUM}
(superseded)"</code></pre>
+ </li>
+ <li>Drop the Nexus staging repository via the <a
href="https://repository.apache.org/#stagingRepositories">Nexus UI</a>.</li>
+ <li>Increment <code>RC_NUM</code>, then go back to <a
href="#build-a-release-candidate">Build a release candidate</a>.</li>
+ </ol>
+
+ <!-- ============================================================
-->
+ <h2 id="finalize-the-release">Finalize the Release</h2>
+
+ <h3>Push the Release Tag</h3>
+ <p>Once the vote passes, create and push the final release tag.
This triggers CI to publish to crates.io and PyPI automatically.</p>
+<pre><code>git checkout v${RELEASE_VERSION}-rc${RC_NUM}
+git tag -s v${RELEASE_VERSION} -m "Release Apache Paimon Mosaic
${RELEASE_VERSION}"
+git push origin v${RELEASE_VERSION}</code></pre>
+
+ <h3>Move Source Artifacts to the Release Repository</h3>
+<pre><code>svn mv -m "Release paimon-mosaic ${RELEASE_VERSION}" \
+
https://dist.apache.org/repos/dist/dev/paimon/paimon-mosaic-${RELEASE_VERSION}-rc${RC_NUM}
\
+
https://dist.apache.org/repos/dist/release/paimon/paimon-mosaic-${RELEASE_VERSION}</code></pre>
+
+ <h3>Release the Java Artifacts</h3>
+ <ol>
+ <li>Go to <a
href="https://repository.apache.org/#stagingRepositories">Apache Nexus Staging
Repositories</a>.</li>
+ <li>Find the staging repository for
<code>orgapachepaimon-XXXX</code>.</li>
+ <li><strong>Close</strong> the repository (runs validation
rules).</li>
+ <li>Once closed, <strong>Release</strong> the repository to
Maven Central.</li>
+ </ol>
+
+ <h3>Verify Published Artifacts</h3>
+ <ul>
+ <li><strong>Rust:</strong> <a
href="https://crates.io/crates/paimon-mosaic-core">crates.io/crates/paimon-mosaic-core</a>
shows version <code>${RELEASE_VERSION}</code></li>
+ <li><strong>Java:</strong> <a
href="https://search.maven.org/search?q=g:org.apache.paimon%20a:mosaic">Maven
Central</a> shows version <code>${RELEASE_VERSION}</code></li>
+ <li><strong>Python:</strong> <a
href="https://pypi.org/project/paimon-mosaic/">PyPI — paimon-mosaic</a>
shows version <code>${RELEASE_VERSION}</code></li>
+ </ul>
+
+ <h3>Create GitHub Release</h3>
+ <ol>
+ <li>Go to <a
href="https://github.com/apache/paimon-mosaic/releases/new">Releases —
New release</a>.</li>
+ <li>Choose tag <code>v${RELEASE_VERSION}</code>.</li>
+ <li>Click <strong>Generate release notes</strong> and
review.</li>
+ <li>Click <strong>Publish release</strong>.</li>
+ </ol>
+
+ <p><strong>Checklist:</strong></p>
+ <ul>
+ <li>Release tag pushed; CI published to crates.io and PyPI</li>
+ <li>Source artifacts moved to <a
href="https://dist.apache.org/repos/dist/release/paimon/">dist release</a></li>
+ <li>Java artifacts released to Maven Central via Nexus</li>
+ <li>GitHub Release created</li>
+ </ul>
+
+ <!-- ============================================================
-->
+ <h2 id="promote-the-release">Promote the Release</h2>
+
+ <h3>Update the Releases Page</h3>
+ <p>Update the <a href="releases.html">Releases</a> page: move the
released version from "Upcoming" to "Past Releases" with a summary of key
features and a link to the GitHub release notes.</p>
+
+ <h3>Announce the Release</h3>
+ <p>Wait at least 24 hours after finalizing. Send the announcement
to <code>[email protected]</code> and <code>[email protected]</code>
using your <code>@apache.org</code> email in <strong>plain text</strong>.</p>
+ <p><strong>Subject:</strong> <code>[ANNOUNCE] Release Apache
Paimon Mosaic ${RELEASE_VERSION}</code></p>
+<pre><code>The Apache Paimon community is pleased to announce the release of
+Apache Paimon Mosaic ${RELEASE_VERSION}.
+
+Apache Paimon Mosaic is a columnar-bucket hybrid format optimized for
+wide tables of Apache Paimon.
+
+Rust: cargo add paimon-mosaic-core
+Java: <dependency>
+ <groupId>org.apache.paimon</groupId>
+ <artifactId>mosaic</artifactId>
+ <version>${RELEASE_VERSION}</version>
+ </dependency>
+Python: pip install paimon-mosaic
+
+Release notes:
+https://github.com/apache/paimon-mosaic/releases/tag/v${RELEASE_VERSION}
+
+Thanks to all contributors!</code></pre>
+
+ <h3>Clean Up Old Releases</h3>
+ <p>ASF policy requires only the latest release in the dist release
area. Remove older versions:</p>
+<pre><code>svn rm -m "Remove old release" \
+
https://dist.apache.org/repos/dist/release/paimon/paimon-mosaic-${OLD_VERSION}</code></pre>
+ </div>
+ </main>
+</body>
+</html>
diff --git a/docs/design.html b/docs/design.html
index af052e8..84c5e4f 100644
--- a/docs/design.html
+++ b/docs/design.html
@@ -22,7 +22,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Design & Format Specification - Mosaic</title>
+ <title>Design & Format Specification - Paimon Mosaic</title>
<link rel="stylesheet" href="css/style.css">
<script src="js/main.js"></script>
</head>
@@ -32,7 +32,7 @@
<aside class="sidebar">
<div class="sidebar-header">
- <h2>Mosaic</h2>
+ <h2>Paimon Mosaic</h2>
<p>Columnar-bucket hybrid format</p>
</div>
<nav>
@@ -42,6 +42,7 @@
<li><a href="java-api.html">Java API</a></li>
<li><a href="python-api.html">Python API</a></li>
<li><a href="cpp-api.html">C++ API</a></li>
+ <li><a href="releases.html">Releases</a></li>
</ul>
</nav>
<div class="sidebar-footer">
diff --git a/docs/index.html b/docs/index.html
index e22e4e1..55e9ec8 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -22,7 +22,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Mosaic</title>
+ <title>Paimon Mosaic</title>
<link rel="stylesheet" href="css/style.css">
<script src="js/main.js"></script>
</head>
@@ -32,7 +32,7 @@
<aside class="sidebar">
<div class="sidebar-header">
- <h2>Mosaic</h2>
+ <h2>Paimon Mosaic</h2>
<p>Columnar-bucket hybrid format</p>
</div>
<nav>
@@ -42,6 +42,7 @@
<li><a href="java-api.html">Java API</a></li>
<li><a href="python-api.html">Python API</a></li>
<li><a href="cpp-api.html">C++ API</a></li>
+ <li><a href="releases.html">Releases</a></li>
</ul>
</nav>
<div class="sidebar-footer">
diff --git a/docs/java-api.html b/docs/java-api.html
index d6cd7cb..f654b99 100644
--- a/docs/java-api.html
+++ b/docs/java-api.html
@@ -22,7 +22,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Java API - Mosaic</title>
+ <title>Java API - Paimon Mosaic</title>
<link rel="stylesheet" href="css/style.css">
<script src="js/main.js"></script>
</head>
@@ -32,7 +32,7 @@
<aside class="sidebar">
<div class="sidebar-header">
- <h2>Mosaic</h2>
+ <h2>Paimon Mosaic</h2>
<p>Columnar-bucket hybrid format</p>
</div>
<nav>
@@ -42,6 +42,7 @@
<li><a href="java-api.html" class="active">Java API</a></li>
<li><a href="python-api.html">Python API</a></li>
<li><a href="cpp-api.html">C++ API</a></li>
+ <li><a href="releases.html">Releases</a></li>
</ul>
</nav>
<div class="sidebar-footer">
@@ -57,14 +58,14 @@
<h2>Setup</h2>
<p>
The Java API lives in the <code>java/</code> directory and
depends on the
- <code>mosaic_jni</code> native library. Build the native
library first:
+ <code>paimon_mosaic_jni</code> native library. Build the
native library first:
</p>
-<pre><code>cargo build --release -p mosaic-jni</code></pre>
+<pre><code>cargo build --release -p paimon-mosaic-jni</code></pre>
<p>
- Ensure <code>libmosaic_jni.dylib</code> (macOS) or
<code>libmosaic_jni.so</code> (Linux)
+ Ensure <code>libpaimon_mosaic_jni.dylib</code> (macOS) or
<code>libpaimon_mosaic_jni.so</code> (Linux)
is on <code>java.library.path</code>. The library is loaded
automatically via:
</p>
-<pre><code>System.loadLibrary(<span
class="str">"mosaic_jni"</span>);</code></pre>
+<pre><code>System.loadLibrary(<span
class="str">"paimon_mosaic_jni"</span>);</code></pre>
<p>
Add the Arrow Java dependencies to your <code>pom.xml</code>:
</p>
diff --git a/docs/python-api.html b/docs/python-api.html
index d1cd442..7d50afe 100644
--- a/docs/python-api.html
+++ b/docs/python-api.html
@@ -22,7 +22,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Python API - Mosaic</title>
+ <title>Python API - Paimon Mosaic</title>
<link rel="stylesheet" href="css/style.css">
<script src="js/main.js"></script>
</head>
@@ -32,7 +32,7 @@
<aside class="sidebar">
<div class="sidebar-header">
- <h2>Mosaic</h2>
+ <h2>Paimon Mosaic</h2>
<p>Columnar-bucket hybrid format</p>
</div>
<nav>
@@ -42,6 +42,7 @@
<li><a href="java-api.html">Java API</a></li>
<li><a href="python-api.html" class="active">Python
API</a></li>
<li><a href="cpp-api.html">C++ API</a></li>
+ <li><a href="releases.html">Releases</a></li>
</ul>
</nav>
<div class="sidebar-footer">
@@ -57,11 +58,11 @@
<h2>Setup</h2>
<p>
The Python API lives in the <code>python/</code> directory and
depends on the
- <code>mosaic_ffi</code> shared library and
<code>pyarrow</code>.
+ <code>paimon_mosaic_ffi</code> shared library and
<code>pyarrow</code>.
Build the native library first, then install the Python
package:
</p>
<pre><code><span class="cmt"># 1. Build the native library</span>
-cargo build --release -p mosaic-ffi
+cargo build --release -p paimon-mosaic-ffi
<span class="cmt"># 2. Install the Python package (bundles the native lib
automatically)</span>
cd python
diff --git a/docs/releases.html b/docs/releases.html
new file mode 100644
index 0000000..2e6b35b
--- /dev/null
+++ b/docs/releases.html
@@ -0,0 +1,98 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>Releases - Paimon Mosaic</title>
+ <link rel="stylesheet" href="css/style.css">
+ <script src="js/main.js"></script>
+</head>
+<body>
+ <button class="menu-toggle" aria-label="Menu">☰</button>
+ <div class="overlay"></div>
+
+ <aside class="sidebar">
+ <div class="sidebar-header">
+ <h2>Paimon Mosaic</h2>
+ <p>Columnar-bucket hybrid format</p>
+ </div>
+ <nav>
+ <ul>
+ <li><a href="index.html">Home</a></li>
+ <li><a href="design.html">Design</a></li>
+ <li><a href="java-api.html">Java API</a></li>
+ <li><a href="python-api.html">Python API</a></li>
+ <li><a href="cpp-api.html">C++ API</a></li>
+ <li><a href="releases.html" class="active">Releases</a></li>
+ </ul>
+ </nav>
+ <div class="sidebar-footer">
+ <button class="theme-toggle">Dark Mode</button>
+ </div>
+ </aside>
+
+ <main class="main">
+ <div class="content">
+ <h1>Releases</h1>
+ <p class="subtitle">Release history and download links for Apache
Paimon Mosaic.</p>
+
+ <h2>Release Policy</h2>
+ <p>Apache Paimon Mosaic follows <a
href="https://semver.org/">Semantic Versioning</a>. Releases are published
to:</p>
+ <table>
+ <thead>
+ <tr><th>Component</th><th>Registry</th></tr>
+ </thead>
+ <tbody>
+ <tr><td>Rust</td><td><a
href="https://crates.io/crates/paimon-mosaic-core">crates.io/crates/paimon-mosaic-core</a></td></tr>
+ <tr><td>Java</td><td><a
href="https://search.maven.org/search?q=g:org.apache.paimon%20a:mosaic">Maven
Central</a> (groupId: <code>org.apache.paimon</code>, artifactId:
<code>mosaic</code>)</td></tr>
+ <tr><td>Python</td><td><a
href="https://pypi.org/project/paimon-mosaic/">PyPI —
paimon-mosaic</a></td></tr>
+ </tbody>
+ </table>
+
+ <h2>Upcoming</h2>
+
+ <h3>0.1.0 (In Development)</h3>
+ <p>The first release of Apache Paimon Mosaic. Planned features:</p>
+ <ul>
+ <li>Mosaic columnar-bucket hybrid format core
implementation</li>
+ <li>High-performance reader and writer with ZSTD
compression</li>
+ <li>Arrow-compatible data exchange via C Data Interface</li>
+ <li>Java binding with JNI (multi-platform native
libraries)</li>
+ <li>Python binding with FFI</li>
+ <li>C++ headers for native integration</li>
+ </ul>
+
+ <h2>Past Releases</h2>
+ <p>(None yet)</p>
+
+ <h2>Download</h2>
+ <p>Official source releases are available from the <a
href="https://downloads.apache.org/paimon/">ASF distribution</a>.</p>
+
+ <h2>Release Guides</h2>
+ <ul>
+ <li><a href="creating-a-release.html">Creating a Release</a>
— for Release Managers</li>
+ <li><a href="verifying-a-release-candidate.html">Verifying a
Release Candidate</a> — for vote participants</li>
+ </ul>
+ </div>
+ </main>
+</body>
+</html>
diff --git a/docs/verifying-a-release-candidate.html
b/docs/verifying-a-release-candidate.html
new file mode 100644
index 0000000..1ec53e0
--- /dev/null
+++ b/docs/verifying-a-release-candidate.html
@@ -0,0 +1,196 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>Verifying a Release Candidate - Paimon Mosaic</title>
+ <link rel="stylesheet" href="css/style.css">
+ <script src="js/main.js"></script>
+</head>
+<body>
+ <button class="menu-toggle" aria-label="Menu">☰</button>
+ <div class="overlay"></div>
+
+ <aside class="sidebar">
+ <div class="sidebar-header">
+ <h2>Paimon Mosaic</h2>
+ <p>Columnar-bucket hybrid format</p>
+ </div>
+ <nav>
+ <ul>
+ <li><a href="index.html">Home</a></li>
+ <li><a href="design.html">Design</a></li>
+ <li><a href="java-api.html">Java API</a></li>
+ <li><a href="python-api.html">Python API</a></li>
+ <li><a href="cpp-api.html">C++ API</a></li>
+ <li><a href="releases.html">Releases</a></li>
+ </ul>
+ </nav>
+ <div class="sidebar-footer">
+ <button class="theme-toggle">Dark Mode</button>
+ </div>
+ </aside>
+
+ <main class="main">
+ <div class="content">
+ <h1>Verifying a Release Candidate</h1>
+ <p class="subtitle">Guide for anyone participating in the release
vote, based on <a href="https://www.apache.org/legal/release-policy.html">ASF
Release Policy</a>.</p>
+
+ <!-- ============================================================
-->
+ <h2>Validating Distributions</h2>
+ <p>The release vote email includes links to:</p>
+ <ul>
+ <li><strong>Distribution archive:</strong> source tarball
(<code>apache-paimon-mosaic-${RELEASE_VERSION}-src.tgz</code>) on <a
href="https://dist.apache.org/repos/dist/dev/paimon/">dist.apache.org
dev</a></li>
+ <li><strong>Signature file:</strong>
<code>apache-paimon-mosaic-${RELEASE_VERSION}-src.tgz.asc</code></li>
+ <li><strong>Checksum file:</strong>
<code>apache-paimon-mosaic-${RELEASE_VERSION}-src.tgz.sha512</code></li>
+ <li><strong>KEYS file:</strong> <a
href="https://downloads.apache.org/paimon/KEYS">https://downloads.apache.org/paimon/KEYS</a></li>
+ </ul>
+ <p>Download the archive (<code>.tgz</code>), <code>.asc</code>,
and <code>.sha512</code> from the RC directory (e.g.
<code>paimon-mosaic-${RELEASE_VERSION}-rc${RC_NUM}/</code>) and the KEYS
file.</p>
+
+ <!-- ============================================================
-->
+ <h2>Verifying Signatures</h2>
+ <p>Import the keys into your local keyring:</p>
+<pre><code>curl https://downloads.apache.org/paimon/KEYS -o KEYS
+gpg --import KEYS</code></pre>
+ <p>Verify the <code>.asc</code> file:</p>
+<pre><code>gpg --verify apache-paimon-mosaic-${RELEASE_VERSION}-src.tgz.asc \
+ apache-paimon-mosaic-${RELEASE_VERSION}-src.tgz</code></pre>
+ <p>If verification succeeds, you will see:</p>
+<pre><code>gpg: Signature made ...
+gpg: using RSA key ...
+gpg: Good signature from "Release Manager Name (CODE SIGNING KEY)
<[email protected]>"</code></pre>
+
+ <!-- ============================================================
-->
+ <h2>Verifying Checksums</h2>
+ <p><strong>On macOS (shasum):</strong></p>
+<pre><code>shasum -a 512 -c
apache-paimon-mosaic-${RELEASE_VERSION}-src.tgz.sha512</code></pre>
+ <p><strong>On Linux (sha512sum):</strong></p>
+<pre><code>sha512sum -c
apache-paimon-mosaic-${RELEASE_VERSION}-src.tgz.sha512</code></pre>
+ <p>If successful:</p>
+<pre><code>apache-paimon-mosaic-${RELEASE_VERSION}-src.tgz: OK</code></pre>
+
+ <!-- ============================================================
-->
+ <h2>Verifying Build</h2>
+ <p>Extract the source release and verify it builds. You need
<strong>Rust</strong> (stable toolchain).</p>
+<pre><code>tar -xzf apache-paimon-mosaic-${RELEASE_VERSION}-src.tgz
+cd paimon-mosaic-${RELEASE_VERSION}</code></pre>
+
+ <h3>Rust</h3>
+ <p>Build and test all workspace crates:</p>
+<pre><code>cargo build --workspace --release
+cargo test --workspace</code></pre>
+
+ <h3>Java</h3>
+ <p>Build the Java binding (requires JDK 8+ and Maven):</p>
+<pre><code>cargo build --release -p paimon-mosaic-jni
+cp target/release/libpaimon_mosaic_jni.* java/src/main/resources/native/
+cd java
+mvn clean package</code></pre>
+
+ <h3>Python</h3>
+ <p>Build and test the Python binding (requires Python 3.9+):</p>
+<pre><code>cargo build --release -p paimon-mosaic-ffi
+cp target/release/libpaimon_mosaic_ffi.* python/mosaic/
+cd python
+pip install -e .
+python -c "import mosaic"</code></pre>
+
+ <h3>C++</h3>
+ <p>Build the C++ tests (requires CMake):</p>
+<pre><code>cargo build --release -p paimon-mosaic-ffi
+cd cpp
+mkdir build && cd build
+cmake ..
+make</code></pre>
+
+ <!-- ============================================================
-->
+ <h2>Verifying LICENSE and NOTICE</h2>
+ <p>Verify that:</p>
+ <ol>
+ <li>The <strong>LICENSE</strong> and <strong>NOTICE</strong>
files exist in the root directory and are correct.</li>
+ <li>All source files have ASF license headers.</li>
+ <li>All dependencies have licenses compatible with ASL 2.0 (<a
href="http://www.apache.org/legal/resolved.html#category-x">ASF third-party
license policy</a>).</li>
+ <li>No unexpected files are included (<code>.git</code>,
<code>.github</code>, <code>.asf.yaml</code>, <code>.gitignore</code>,
<code>.idea</code>, <code>target/</code> should all be excluded).</li>
+ </ol>
+
+ <!-- ============================================================
-->
+ <h2>Testing Published Artifacts</h2>
+
+ <h3>Rust (crates.io)</h3>
+ <p>RC tags do <strong>not</strong> publish to crates.io (dry-run
only). You can test the Rust crate from the source tarball or via git tag
dependency:</p>
+<pre><code>[dependencies]
+paimon-mosaic-core = { git = "https://github.com/apache/paimon-mosaic", tag =
"v${RELEASE_VERSION}-rc${RC_NUM}" }</code></pre>
+
+ <h3>Java (Apache Nexus Staging)</h3>
+ <p>The RC tag deploys to Apache Nexus staging. To test:</p>
+ <ol>
+ <li>Find the staging repository at <a
href="https://repository.apache.org/#stagingRepositories">repository.apache.org</a>.</li>
+ <li>Add the staging repository URL to your
<code>pom.xml</code>:
+<pre><code><repositories>
+ <repository>
+ <id>apache-staging</id>
+
<url>https://repository.apache.org/content/repositories/orgapachepaimon-XXXX/</url>
+ </repository>
+</repositories></code></pre>
+ </li>
+ <li>Add the dependency:
+<pre><code><dependency>
+ <groupId>org.apache.paimon</groupId>
+ <artifactId>mosaic</artifactId>
+ <version>${RELEASE_VERSION}</version>
+</dependency></code></pre>
+ </li>
+ <li>Verify the JAR contains native libraries for all 4
platforms:
+ <ul>
+
<li><code>native/linux/x86_64/libpaimon_mosaic_jni.so</code></li>
+
<li><code>native/linux/aarch64/libpaimon_mosaic_jni.so</code></li>
+
<li><code>native/macos/aarch64/libpaimon_mosaic_jni.dylib</code></li>
+
<li><code>native/windows/x86_64/paimon_mosaic_jni.dll</code></li>
+ </ul>
+ </li>
+ </ol>
+
+ <h3>Python (TestPyPI)</h3>
+ <p>The RC tag publishes wheels to TestPyPI. Install and verify:</p>
+<pre><code>pip install -i https://test.pypi.org/simple/
paimon-mosaic==${RELEASE_VERSION}rc${RC_NUM}
+python -c "import mosaic; print('OK')"</code></pre>
+ <p>Verify wheels are available for: Linux x86_64, Linux aarch64,
macOS aarch64, Windows x86_64.</p>
+
+ <!-- ============================================================
-->
+ <h2>Voting</h2>
+ <p>Votes are cast by replying to the vote email on the dev mailing
list with <strong>+1</strong>, <strong>0</strong>, or <strong>-1</strong>.</p>
+ <p>State whether your vote is <strong>binding</strong> or
<strong>non-binding</strong>. Only PMC members have formally binding votes. See
<a href="https://www.apache.org/foundation/voting.html">Apache Foundation
Voting</a>.</p>
+ <p>Include a short list of what you verified. This helps the
community see what has been checked.</p>
+
+ <p><strong>Checklist you can reference in your vote:</strong></p>
+ <ul>
+ <li>Validating distributions</li>
+ <li>Verifying signatures</li>
+ <li>Verifying checksums</li>
+ <li>Verifying build</li>
+ <li>Verifying LICENSE and NOTICE</li>
+ <li>Testing published artifacts</li>
+ </ul>
+ </div>
+ </main>
+</body>
+</html>
diff --git a/ffi/Cargo.toml b/ffi/Cargo.toml
index e690775..e44036b 100644
--- a/ffi/Cargo.toml
+++ b/ffi/Cargo.toml
@@ -16,7 +16,7 @@
# under the License.
[package]
-name = "mosaic-ffi"
+name = "paimon-mosaic-ffi"
version = "0.1.0"
edition = "2021"
description = "Mosaic file format — C/C++ FFI bindings"
@@ -26,7 +26,7 @@ license = "Apache-2.0"
crate-type = ["cdylib"]
[dependencies]
-mosaic-core = { path = "../core" }
+mosaic-core = { path = "../core", package = "paimon-mosaic-core" }
arrow-schema = "58"
arrow-array = { version = "58", features = ["ffi"] }
diff --git a/java/src/main/java/org/apache/paimon/mosaic/NativeLib.java
b/java/src/main/java/org/apache/paimon/mosaic/NativeLib.java
index 366a237..62ffd81 100644
--- a/java/src/main/java/org/apache/paimon/mosaic/NativeLib.java
+++ b/java/src/main/java/org/apache/paimon/mosaic/NativeLib.java
@@ -28,7 +28,7 @@ import java.nio.file.StandardCopyOption;
final class NativeLib {
- private static final String LIB_NAME = "mosaic_jni";
+ private static final String LIB_NAME = "paimon_mosaic_jni";
static {
loadNativeLibrary();
@@ -55,7 +55,7 @@ final class NativeLib {
throw new UnsatisfiedLinkError(
"Native library not found in JAR: " + resourcePath);
}
- File tempFile = File.createTempFile("mosaic_jni", libFileName);
+ File tempFile = File.createTempFile("paimon_mosaic_jni",
libFileName);
tempFile.deleteOnExit();
Files.copy(in, tempFile.toPath(),
StandardCopyOption.REPLACE_EXISTING);
System.load(tempFile.getAbsolutePath());
@@ -90,11 +90,11 @@ final class NativeLib {
private static String mapLibraryName(String os) {
switch (os) {
case "linux":
- return "libmosaic_jni.so";
+ return "libpaimon_mosaic_jni.so";
case "macos":
- return "libmosaic_jni.dylib";
+ return "libpaimon_mosaic_jni.dylib";
case "windows":
- return "mosaic_jni.dll";
+ return "paimon_mosaic_jni.dll";
default:
throw new UnsatisfiedLinkError("Unsupported OS: " + os);
}
diff --git a/jni/Cargo.toml b/jni/Cargo.toml
index 1cf0142..f55019d 100644
--- a/jni/Cargo.toml
+++ b/jni/Cargo.toml
@@ -16,7 +16,7 @@
# under the License.
[package]
-name = "mosaic-jni"
+name = "paimon-mosaic-jni"
version = "0.1.0"
edition = "2021"
description = "Mosaic file format — JNI bindings for Java"
@@ -26,7 +26,7 @@ license = "Apache-2.0"
crate-type = ["cdylib"]
[dependencies]
-mosaic-core = { path = "../core" }
+mosaic-core = { path = "../core", package = "paimon-mosaic-core" }
jni = "0.21"
arrow-schema = "58"
arrow-array = { version = "58", features = ["ffi"] }
diff --git a/python/mosaic/_ffi.py b/python/mosaic/_ffi.py
index 625369b..1b94438 100644
--- a/python/mosaic/_ffi.py
+++ b/python/mosaic/_ffi.py
@@ -43,11 +43,11 @@ from ctypes import (
def _load_library():
system = platform.system()
if system == "Darwin":
- lib_name = "libmosaic_ffi.dylib"
+ lib_name = "libpaimon_mosaic_ffi.dylib"
elif system == "Windows":
- lib_name = "mosaic_ffi.dll"
+ lib_name = "paimon_mosaic_ffi.dll"
else:
- lib_name = "libmosaic_ffi.so"
+ lib_name = "libpaimon_mosaic_ffi.so"
env_path = os.environ.get("MOSAIC_LIB_PATH")
search_paths = []
@@ -76,7 +76,7 @@ def _load_library():
except OSError:
raise OSError(
f"Cannot find {lib_name}. Build the native library first with "
- f"'cargo build --release -p mosaic-ffi', or set MOSAIC_LIB_PATH "
+ f"'cargo build --release -p paimon-mosaic-ffi', or set
MOSAIC_LIB_PATH "
f"to the directory containing {lib_name}."
)
diff --git a/python/pyproject.toml b/python/pyproject.toml
index 893b319..08dc185 100644
--- a/python/pyproject.toml
+++ b/python/pyproject.toml
@@ -20,7 +20,7 @@ requires = ["setuptools>=64"]
build-backend = "setuptools.build_meta"
[project]
-name = "mosaic-format"
+name = "paimon-mosaic"
version = "0.1.0"
description = "Python bindings for the Mosaic columnar-bucket hybrid file
format"
license = {text = "Apache-2.0"}
@@ -34,4 +34,4 @@ test = ["pytest"]
include = ["mosaic*"]
[tool.setuptools.package-data]
-mosaic = ["libmosaic_ffi.dylib", "libmosaic_ffi.so", "mosaic_ffi.dll"]
+mosaic = ["libpaimon_mosaic_ffi.dylib", "libpaimon_mosaic_ffi.so",
"paimon_mosaic_ffi.dll"]
diff --git a/python/setup.py b/python/setup.py
index 0725345..d1a6569 100644
--- a/python/setup.py
+++ b/python/setup.py
@@ -29,10 +29,10 @@ from wheel.bdist_wheel import bdist_wheel
def _lib_name():
system = platform.system()
if system == "Darwin":
- return "libmosaic_ffi.dylib"
+ return "libpaimon_mosaic_ffi.dylib"
elif system == "Windows":
- return "mosaic_ffi.dll"
- return "libmosaic_ffi.so"
+ return "paimon_mosaic_ffi.dll"
+ return "libpaimon_mosaic_ffi.so"
def _find_native_lib():
diff --git a/tools/releasing/create_source_release.sh
b/tools/releasing/create_source_release.sh
index 816a775..e7beca2 100755
--- a/tools/releasing/create_source_release.sh
+++ b/tools/releasing/create_source_release.sh
@@ -17,6 +17,13 @@
# limitations under the License.
#
+# Create ASF source release artifacts under tools/release/:
+# apache-paimon-mosaic-{version}-src.tgz
+# apache-paimon-mosaic-{version}-src.tgz.asc
+# apache-paimon-mosaic-{version}-src.tgz.sha512
+#
+# Usage: cd tools && RELEASE_VERSION=0.1.0 ./releasing/create_source_release.sh
+
##
## Variables with defaults (if not overwritten by environment)
##
@@ -59,7 +66,7 @@ echo "Creating source package"
git clone . tools/release/paimon-mosaic-tmp-clone
cd tools/release/paimon-mosaic-tmp-clone
-trap 'cd ${CURR_DIR};rm -rf release' ERR
+trap 'cd ${CURR_DIR}/release;rm -rf paimon-mosaic-tmp-clone' ERR
rsync -a \
--exclude ".git" --exclude ".gitignore" --exclude ".gitattributes" \
@@ -72,6 +79,18 @@ tar czf apache-paimon-mosaic-${RELEASE_VERSION}-src.tgz
paimon-mosaic-$RELEASE_V
gpg --armor --detach-sig apache-paimon-mosaic-$RELEASE_VERSION-src.tgz
$SHASUM apache-paimon-mosaic-$RELEASE_VERSION-src.tgz >
apache-paimon-mosaic-$RELEASE_VERSION-src.tgz.sha512
+echo "Verifying GPG signature"
+gpg --verify apache-paimon-mosaic-$RELEASE_VERSION-src.tgz.asc
apache-paimon-mosaic-$RELEASE_VERSION-src.tgz
+
+echo "Verifying tarball integrity"
+tar tzf apache-paimon-mosaic-${RELEASE_VERSION}-src.tgz > /dev/null
+
mv apache-paimon-mosaic-$RELEASE_VERSION-src.* ../
cd ..
rm -rf paimon-mosaic-tmp-clone
+
+echo ""
+echo "Source release created successfully. Artifacts in tools/release/:"
+ls -la ${CURR_DIR}/release/apache-paimon-mosaic-*
+echo ""
+echo "Next: upload contents to SVN (see docs/creating-a-release.html)."
diff --git a/tools/releasing/update_branch_version.sh
b/tools/releasing/update_branch_version.sh
index 31e591f..03ec8a8 100755
--- a/tools/releasing/update_branch_version.sh
+++ b/tools/releasing/update_branch_version.sh
@@ -52,14 +52,17 @@ fi
cd ..
-#change version in all pom files
-find . -name 'pom.xml' -type f -exec perl -pi -e
's#<version>'$OLD_VERSION'</version>#<version>'$NEW_VERSION'</version>#' {} \;
+# For Cargo.toml and pyproject.toml, strip any -SNAPSHOT suffix (not valid in
those ecosystems)
+NEW_VERSION_CLEAN=$(echo "$NEW_VERSION" | sed 's/-SNAPSHOT//')
+
+#change version in all pom files (match both exact and -SNAPSHOT suffix)
+find . -name 'pom.xml' -type f -exec perl -pi -e
's#<version>'$OLD_VERSION'(-SNAPSHOT)?</version>#<version>'$NEW_VERSION'</version>#'
{} \;
#change version in Cargo.toml files
-find . -name 'Cargo.toml' -not -path '*/target/*' -type f -exec perl -pi -e
's#^version = "'$OLD_VERSION'"#version = "'$NEW_VERSION'"#' {} \;
+find . -name 'Cargo.toml' -not -path '*/target/*' -type f -exec perl -pi -e
's#^version = "'$OLD_VERSION'"#version = "'$NEW_VERSION_CLEAN'"#' {} \;
#change version in pyproject.toml
-perl -pi -e 's#^version = "'$OLD_VERSION'"#version = "'$NEW_VERSION'"#'
python/pyproject.toml
+perl -pi -e 's#^version = "'$OLD_VERSION'"#version = "'$NEW_VERSION_CLEAN'"#'
python/pyproject.toml
git commit -am "Update version to $NEW_VERSION"