Skip to content

Commit 2198249

Browse files
authored
Merge branch 'main' into update_commit_message_version
2 parents 48a87d0 + ed60097 commit 2198249

48 files changed

Lines changed: 1121 additions & 227 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.asf.yaml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
#
1919

2020
# The format of this file is documented at
21-
# https://cwiki.apache.org/confluence/display/INFRA/Git+-+.asf.yaml+features
21+
# https://github.com/apache/infrastructure-asfyaml
2222

2323
github:
2424
description: "Paimon-cpp is a high-performance C++ implementation of Apache Paimon."
@@ -29,6 +29,11 @@ github:
2929
- paimon
3030
- apache
3131
- cpp
32+
collaborators:
33+
- zjw1111
34+
- lxy-9602
35+
- lucasfang
36+
- lszskye
3237
enabled_merge_buttons:
3338
merge: false
3439
squash: true

.github/workflows/release_candidate.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,13 @@ jobs:
7878
--output-dir release/ci
7979
8080
- name: Audit source archive
81+
env:
82+
# The creator must ignore caller-provided gzip defaults.
83+
GZIP: "-9"
8184
run: |
8285
scripts/releasing/verify_release_candidate.sh \
8386
--allow-unsigned \
87+
--git-ref HEAD \
8488
--skip-build \
8589
"release/ci/apache-paimon-cpp-${RELEASE_VERSION}-src.tgz"
8690

docs/source/user_guide/data_types.rst

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -188,15 +188,14 @@ and `Arrow DataTypes <https://arrow.apache.org/docs/format/Columnar.html#data-ty
188188

189189
* - ``MAP<kt, vt>``
190190
- Map
191-
- Data type of an associative array that maps keys to values (including NULL). A map cannot contain duplicate keys; each key can map to at most one value.
191+
- Data type of an associative array that maps keys (including NULL) to values (including NULL). A map cannot contain duplicate keys; each key can map to at most one value.
192192

193193
There is no restriction of element types; it is the responsibility of the user to ensure uniqueness.
194194

195195
The type can be declared using ``MAP<kt, vt>`` where kt is the data type of the key elements and vt is the data type of the value elements.
196196

197-
**Note:** In Paimon C++, map keys must be explicitly marked as ``NOT NULL``.
198-
Apache Arrow does not support nullable map keys. If the key type is not
199-
marked as ``NOT NULL`` in the schema, parsing will fail with an error.
197+
**Note:** Paimon C++ accepts nullable map key declarations for schema compatibility.
198+
A query fails only if the data actually contains a NULL map key.
200199

201200
* - ``MULTISET<t>``
202201
- Not Supported

docs/source/user_guide/schema.rst

Lines changed: 4 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -84,35 +84,11 @@ DataField represents a column of the table.
8484
3. ``type``: data type, very similar to SQL type string.
8585
4. ``description``: string.
8686

87-
Limitations
88-
-----------
87+
Nullable MAP Keys
88+
-----------------
8989

90-
MAP Key Must Be NOT NULL
91-
^^^^^^^^^^^^^^^^^^^^^^^^
92-
93-
Apache Arrow does not support nullable map keys. When defining a ``MAP`` type in the schema,
94-
the key must be explicitly marked as ``NOT NULL``. If the key is not marked as ``NOT NULL``,
95-
schema parsing will fail with an error.
96-
97-
For example, the following is **valid**:
98-
99-
.. code-block:: json
100-
101-
{
102-
"type": "MAP",
103-
"key": "TINYINT NOT NULL",
104-
"value": "SMALLINT"
105-
}
106-
107-
The following is **invalid** and will be rejected:
108-
109-
.. code-block:: json
110-
111-
{
112-
"type": "MAP",
113-
"key": "TINYINT",
114-
"value": "SMALLINT"
115-
}
90+
Paimon C++ accepts nullable ``MAP`` key declarations for compatibility with existing schemas.
91+
A query fails only when the data actually contains a NULL map key.
11692

11793
Update Schema
11894
-------------

scripts/releasing/README.md

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,25 @@ Before starting a release:
3434
- obtain an ASF code-signing key, publish it through the ASF account system,
3535
and make sure it is present in
3636
[Paimon KEYS](https://downloads.apache.org/paimon/KEYS);
37-
- install `git`, `gpg`, `svn`, `gh`, `python3`, `curl` or `wget`, Java, CMake,
38-
Ninja, and the toolchain needed by `ci/scripts/build_paimon.sh` (Java is
39-
required by Apache RAT);
37+
- install `git`, GNU `gzip`, `gpg`, `svn`, `gh`, `python3`, `curl` or `wget`,
38+
Java, CMake, Ninja, and the toolchain needed by
39+
`ci/scripts/build_paimon.sh` (Java is required by Apache RAT);
4040
- authenticate `gh` with access to read GitHub Actions runs in
4141
`apache/paimon-cpp`;
4242
- make sure the Apache Git remote points directly to
4343
`apache/paimon-cpp`;
4444
- prepare and merge a release-preparation PR that updates the release notes and
4545
all version metadata, and passes the normal and release-candidate workflows.
4646

47+
The source archive uses GNU gzip with fixed options so that macOS and Linux
48+
produce the same bytes. On macOS, install Homebrew gzip and either put it first
49+
on `PATH` or select it explicitly:
50+
51+
```bash
52+
brew install gzip
53+
export PAIMON_GZIP="$(brew --prefix gzip)/bin/gzip"
54+
```
55+
4756
For example, update all version locations and review the diff:
4857

4958
```bash
@@ -80,10 +89,13 @@ The release scripts use `vVERSION-rcRC` for release-candidate tags and
8089

8190
Start from the exact clean commit approved for the candidate. Before publishing,
8291
the wrapper fetches the release branch and requires `HEAD` to be contained in
83-
its current history. It then creates and verifies a signed RC tag, creates the
84-
source archive and its checksum/signature, performs the full source-release
85-
verification, pushes the tag, waits for the tag-triggered release-candidate
86-
workflow to succeed, and imports the artifacts into ASF `dist/dev`:
92+
its current history. It then creates and verifies a signed RC tag, pushes the
93+
tag, and waits for the tag-triggered release-candidate workflow. That workflow
94+
creates the canonical source archive and checksum, builds and tests the same
95+
archive with GCC and Clang, and uploads it as a workflow artifact. The wrapper
96+
downloads those exact bytes, confirms that they are reproducible from the tag,
97+
signs the archive locally, performs the full source-release verification, and
98+
imports the three files into ASF `dist/dev`:
8799

88100
```bash
89101
scripts/releasing/release_rc.sh \
@@ -96,12 +108,13 @@ scripts/releasing/release_rc.sh \
96108
The release branch defaults to `main`; use `--release-branch NAME` for a
97109
maintenance release from another Apache branch.
98110

99-
Use `--prepare-only` to create and verify artifacts without pushing the tag or
100-
uploading to ASF infrastructure. This local-only mode does not require `HEAD`
101-
to match the remote release branch. Use `--dry-run` to print identifiers
102-
without making changes. A resumed run reuses an existing local tag or complete
103-
artifact set only after validating it. A prepare-only run does not print a vote
104-
email and must not be used to start a vote.
111+
Use `--prepare-only` to create and verify preview artifacts without pushing the
112+
tag or uploading to ASF infrastructure. This local-only mode does not require
113+
`HEAD` to match the remote release branch. A preview is not authoritative: a
114+
published run downloads the workflow artifact and rejects an existing local
115+
archive if its bytes differ. Use `--dry-run` to print identifiers without
116+
making changes. A prepare-only run does not print a vote email and must not be
117+
used to start a vote.
105118

106119
The candidate directory contains:
107120

@@ -164,13 +177,16 @@ The verifier checks:
164177
- installation plus compilation and execution of an external CMake consumer.
165178

166179
Pass `--git-ref v0.3.0-rc1` when the Git repository is available to regenerate
167-
the archive from the signed tag and compare it byte-for-byte.
180+
the archive from the signed tag with GNU gzip and compare it byte-for-byte.
181+
This check requires GNU gzip on every platform; it intentionally rejects the
182+
macOS system gzip instead of treating different compressed bytes as equivalent.
168183

169184
`--allow-unsigned`, `--skip-rat`, `--skip-build`, and `--skip-install` exist for
170185
CI or local development of the release process. They are not a substitute for
171186
the corresponding checks when voting. The release-candidate workflow creates
172-
an unsigned archive for deterministic CI validation; official artifacts must
173-
always be signed by the release manager.
187+
the unsigned canonical archive for deterministic CI validation. The release
188+
manager downloads and signs that exact archive; the private signing key remains
189+
only on the release manager's machine.
174190

175191
## Publish an approved release
176192

@@ -207,8 +223,9 @@ than ASF's general one-hour minimum.
207223

208224
- `bump_version.py`: consistently check or update CMake and documentation
209225
version metadata.
210-
- `create_source_release.sh`: deterministically create an archive, SHA-512
211-
checksum, and optional detached signature from an immutable Git ref.
226+
- `create_source_release.sh`: deterministically create an archive with GNU
227+
gzip, a SHA-512 checksum, and an optional detached signature from an immutable
228+
Git ref.
212229
- `validate_source_archive.py`: reject unsafe or non-portable tar members and
213230
compiled files.
214231
- `verify_release_candidate.sh`: perform voter-facing integrity, license,

scripts/releasing/create_source_release.sh

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ The script creates:
4949
apache-paimon-cpp-VERSION-src.tgz.asc (when --signing-key is provided)
5050
5151
Existing artifacts are never overwritten.
52+
53+
GNU gzip is required so macOS and Linux produce the same compressed bytes.
54+
Set PAIMON_GZIP to an explicit GNU gzip executable when it is not on PATH.
5255
EOF
5356
}
5457

@@ -68,6 +71,36 @@ calculate_sha512() {
6871
fi
6972
}
7073

74+
find_gnu_gzip() {
75+
local candidate
76+
local resolved
77+
local version_line
78+
local -a candidates
79+
80+
if [[ -n "${PAIMON_GZIP:-}" ]]; then
81+
candidates=("${PAIMON_GZIP}")
82+
else
83+
candidates=(gzip ggzip)
84+
fi
85+
86+
for candidate in "${candidates[@]}"; do
87+
if [[ -x "${candidate}" ]]; then
88+
resolved=${candidate}
89+
elif resolved=$(command -v "${candidate}" 2>/dev/null); then
90+
:
91+
else
92+
continue
93+
fi
94+
version_line=$("${resolved}" --version 2>/dev/null | sed -n '1p' || true)
95+
if [[ "${version_line}" =~ ^gzip[[:space:]][0-9] ]]; then
96+
printf '%s\n' "${resolved}"
97+
return 0
98+
fi
99+
done
100+
101+
fail "GNU gzip is required for reproducible source archives; on macOS run 'brew install gzip' and set PAIMON_GZIP to the Homebrew gzip executable"
102+
}
103+
71104
while [[ $# -gt 0 ]]; do
72105
case "$1" in
73106
--version)
@@ -128,6 +161,8 @@ DOCS_VERSION=$(
128161
[[ "${DOCS_VERSION}" == "${RELEASE_VERSION}" ]] ||
129162
fail "documentation version ${DOCS_VERSION:-<missing>} does not match ${RELEASE_VERSION}"
130163

164+
GZIP_BIN=$(find_gnu_gzip)
165+
131166
ARTIFACT_NAME="apache-paimon-cpp-${RELEASE_VERSION}-src.tgz"
132167
ARCHIVE_ROOT="paimon-cpp-${RELEASE_VERSION}"
133168

@@ -147,7 +182,10 @@ git -C "${SOURCE_ROOT}" -c tar.umask=0022 archive \
147182
--format=tar \
148183
--prefix="${ARCHIVE_ROOT}/" \
149184
"${GIT_REF}" |
150-
gzip -n >"${TEMP_DIR}/${ARTIFACT_NAME}"
185+
(
186+
unset GZIP
187+
"${GZIP_BIN}" --no-name --stdout -6
188+
) >"${TEMP_DIR}/${ARTIFACT_NAME}"
151189

152190
SHA512=$(calculate_sha512 "${TEMP_DIR}/${ARTIFACT_NAME}")
153191
printf '%s %s\n' "${SHA512}" "${ARTIFACT_NAME}" \

0 commit comments

Comments
 (0)