Iceberg Rust

Iceberg Rust is a rust implementation for accessing iceberg tables.

Install

Cargo 1.75.0 or later is required to build.

Add iceberg into Cargo.toml dependencies:

iceberg = "0.2.0"

iceberg is under active development, you may want to use the git version instead:

iceberg = { git = "https://github.com/apache/iceberg-rust", rev = "commit-hash" }

Apache Iceberg™ Rust Downloads

The official Apache Iceberg-Rust releases are provided as source artifacts.

Releases

The latest source release is 0.2.0 (asc, sha512).

For older releases, please check the archive.

Notes

  • When downloading a release, please verify the OpenPGP compatible signature (or failing that, check the SHA-512); these should be fetched from the main Apache site.
  • The KEYS file contains the public keys used for signing release. It is recommended that (when possible) a web of trust is used to confirm the identity of these keys.
  • Please download the KEYS as well as the .asc signature files.

To verify the signature of the release artifact

You will need to download both the release artifact and the .asc signature file for that artifact. Then verify the signature by:

  • Download the KEYS file and the .asc signature files for the relevant release artifacts.

  • Import the KEYS file to your GPG keyring:

    gpg --import KEYS
    
  • Verify the signature of the release artifact using the following command:

    gpg --verify <artifact>.asc <artifact>
    

To verify the checksum of the release artifact

You will need to download both the release artifact and the .sha512 checksum file for that artifact. Then verify the checksum by:

shasum -a 512 -c <artifact>.sha512

Catalog

Catalog is the entry point for accessing iceberg tables. You can use a catalog to:

  • Create and list namespaces.
  • Create, load, and drop tables

Currently only rest catalog has been implemented, and other catalogs are under active development. Here is an example of how to create a RestCatalog:

// 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.

use iceberg::{Catalog, NamespaceIdent};
use iceberg_catalog_rest::{RestCatalog, RestCatalogConfig};
use std::collections::HashMap;

#[tokio::main]
async fn main() {
    // Create catalog
    let config = RestCatalogConfig::builder()
        .uri("http://localhost:8080".to_string())
        .build();

    let catalog = RestCatalog::new(config).await.unwrap();

    // List all namespaces
    let all_namespaces = catalog.list_namespaces(None).await.unwrap();
    println!("Namespaces in current catalog: {:?}", all_namespaces);

    let namespace_id =
        NamespaceIdent::from_vec(vec!["ns1".to_string(), "ns11".to_string()]).unwrap();
    // Create namespace
    let ns = catalog
        .create_namespace(
            &namespace_id,
            HashMap::from([("key1".to_string(), "value1".to_string())]),
        )
        .await
        .unwrap();

    println!("Namespace created: {:?}", ns);
}

You can run following code to list all root namespaces:

// 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.

use iceberg::{Catalog, NamespaceIdent};
use iceberg_catalog_rest::{RestCatalog, RestCatalogConfig};
use std::collections::HashMap;

#[tokio::main]
async fn main() {
    // Create catalog
    let config = RestCatalogConfig::builder()
        .uri("http://localhost:8080".to_string())
        .build();

    let catalog = RestCatalog::new(config).await.unwrap();

    // List all namespaces
    let all_namespaces = catalog.list_namespaces(None).await.unwrap();
    println!("Namespaces in current catalog: {:?}", all_namespaces);

    let namespace_id =
        NamespaceIdent::from_vec(vec!["ns1".to_string(), "ns11".to_string()]).unwrap();
    // Create namespace
    let ns = catalog
        .create_namespace(
            &namespace_id,
            HashMap::from([("key1".to_string(), "value1".to_string())]),
        )
        .await
        .unwrap();

    println!("Namespace created: {:?}", ns);
}

Then you can run following code to create namespace:

// 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.

use iceberg::{Catalog, NamespaceIdent};
use iceberg_catalog_rest::{RestCatalog, RestCatalogConfig};
use std::collections::HashMap;

#[tokio::main]
async fn main() {
    // Create catalog
    let config = RestCatalogConfig::builder()
        .uri("http://localhost:8080".to_string())
        .build();

    let catalog = RestCatalog::new(config).await.unwrap();

    // List all namespaces
    let all_namespaces = catalog.list_namespaces(None).await.unwrap();
    println!("Namespaces in current catalog: {:?}", all_namespaces);

    let namespace_id =
        NamespaceIdent::from_vec(vec!["ns1".to_string(), "ns11".to_string()]).unwrap();
    // Create namespace
    let ns = catalog
        .create_namespace(
            &namespace_id,
            HashMap::from([("key1".to_string(), "value1".to_string())]),
        )
        .await
        .unwrap();

    println!("Namespace created: {:?}", ns);
}

Table

After creating Catalog, we can manipulate tables through Catalog.

You can use following code to create a table:

// 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.

use iceberg::spec::{NestedField, PrimitiveType, Schema, Type};
use iceberg::{Catalog, TableCreation, TableIdent};
use iceberg_catalog_rest::{RestCatalog, RestCatalogConfig};
use std::collections::HashMap;

#[tokio::main]
async fn main() {
    // Create catalog
    let config = RestCatalogConfig::builder()
        .uri("http://localhost:8080".to_string())
        .build();

    let catalog = RestCatalog::new(config).await.unwrap();

    let table_id = TableIdent::from_strs(["default", "t1"]).unwrap();

    let table_schema = Schema::builder()
        .with_fields(vec![
            NestedField::optional(1, "foo", Type::Primitive(PrimitiveType::String)).into(),
            NestedField::required(2, "bar", Type::Primitive(PrimitiveType::Int)).into(),
            NestedField::optional(3, "baz", Type::Primitive(PrimitiveType::Boolean)).into(),
        ])
        .with_schema_id(1)
        .with_identifier_field_ids(vec![2])
        .build()
        .unwrap();

    // Create table
    let table_creation = TableCreation::builder()
        .name(table_id.name.clone())
        .schema(table_schema.clone())
        .properties(HashMap::from([("owner".to_string(), "testx".to_string())]))
        .build();

    let table = catalog
        .create_table(&table_id.namespace, table_creation)
        .await
        .unwrap();

    println!("Table created: {:?}", table.metadata());

    let table2 = catalog
        .load_table(&TableIdent::from_strs(["default", "t2"]).unwrap())
        .await
        .unwrap();
    println!("{:?}", table2.metadata());
}

Also, you can load a table directly:

// 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.

use iceberg::spec::{NestedField, PrimitiveType, Schema, Type};
use iceberg::{Catalog, TableCreation, TableIdent};
use iceberg_catalog_rest::{RestCatalog, RestCatalogConfig};
use std::collections::HashMap;

#[tokio::main]
async fn main() {
    // Create catalog
    let config = RestCatalogConfig::builder()
        .uri("http://localhost:8080".to_string())
        .build();

    let catalog = RestCatalog::new(config).await.unwrap();

    let table_id = TableIdent::from_strs(["default", "t1"]).unwrap();

    let table_schema = Schema::builder()
        .with_fields(vec![
            NestedField::optional(1, "foo", Type::Primitive(PrimitiveType::String)).into(),
            NestedField::required(2, "bar", Type::Primitive(PrimitiveType::Int)).into(),
            NestedField::optional(3, "baz", Type::Primitive(PrimitiveType::Boolean)).into(),
        ])
        .with_schema_id(1)
        .with_identifier_field_ids(vec![2])
        .build()
        .unwrap();

    // Create table
    let table_creation = TableCreation::builder()
        .name(table_id.name.clone())
        .schema(table_schema.clone())
        .properties(HashMap::from([("owner".to_string(), "testx".to_string())]))
        .build();

    let table = catalog
        .create_table(&table_id.namespace, table_creation)
        .await
        .unwrap();

    println!("Table created: {:?}", table.metadata());

    let table2 = catalog
        .load_table(&TableIdent::from_strs(["default", "t2"]).unwrap())
        .await
        .unwrap();
    println!("{:?}", table2.metadata());
}

Contributing

First, thank you for contributing to Iceberg Rust! The goal of this document is to provide everything you need to start contributing to iceberg-rust. The following TOC is sorted progressively, starting with the basics and expanding into more specifics.

Your First Contribution

  1. Fork the iceberg-rust repository into your own GitHub account.
  2. Create a new Git branch.
  3. Make your changes.
  4. Submit the branch as a pull request to the main iceberg-rust repo. An iceberg-rust team member should comment and/or review your pull request within a few days. Although, depending on the circumstances, it may take longer.

Workflow

Git Branches

All changes must be made in a branch and submitted as pull requests. iceberg-rust does not adopt any type of branch naming style, but please use something descriptive of your changes.

GitHub Pull Requests

Once your changes are ready you must submit your branch as a pull request.

Title

The pull request title must follow the format outlined in the conventional commits spec. Conventional commits is a standardized format for commit messages. iceberg-rust only requires this format for commits on the main branch. And because iceberg-rust squashes commits before merging branches, this means that only the pull request title must conform to this format.

The following are all good examples of pull request titles:

feat(schema): Add last_updated_ms in schema
docs: add hdfs classpath related troubleshoot
ci: Mark job as skipped if owner is not apache
fix(schema): Ignore prefix if it's empty
refactor: Polish the implementation of read parquet

Reviews & Approvals

All pull requests should be reviewed by at least one iceberg-rust committer.

Merge Style

All pull requests are squash merged. We generally discourage large pull requests that are over 300-500 lines of diff. If you would like to propose a change that is larger we suggest coming onto Iceberg's DEV mailing list or Slack #rust Channel and discuss it with us. This way we can talk through the solution and discuss if a change that large is even needed! This will produce a quicker response to the change and likely produce code that aligns better with our process.

CI

Currently, iceberg-rust uses GitHub Actions to run tests. The workflows are defined in .github/workflows.

Setup

For small or first-time contributions, we recommend the dev container method. Prefer to do it yourself? That's fine too!

Using a dev container environment

iceberg-rust provides a pre-configured dev container that could be used in Github Codespaces, VSCode, JetBrains, JuptyerLab. Please pick up your favourite runtime environment.

The fastest way is:

Open in GitHub Codespaces

Bring your own toolbox

Install rust

iceberg-rust is primarily a Rust project. To build iceberg-rust, you will need to set up Rust development first. We highly recommend using rustup for the setup process.

For Linux or MacOS, use the following command:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

For Windows, download rustup-init.exe from here instead.

Rustup will read iceberg-rust's rust-toolchain.toml and set up everything else automatically. To ensure that everything works correctly, run cargo version under iceberg-rust's root directory:

$ cargo version
cargo 1.69.0 (6e9a83356 2023-04-12)

Install docker

Currently, iceberg-rust uses docker to set up environment for integration tests.

You can learn how to install docker from here.

For macos users, you can install OrbStack as a docker alternative.

Build

  • To compile the project: make build
  • To check code styles: make check
  • To run unit tests only: make unit-test
  • To run all tests: make test

Code of Conduct

We expect all community members to follow our Code of Conduct.

This document mainly introduces how the release manager releases a new version in accordance with the Apache requirements.

Introduction

Source Release is the key point which Apache values, and is also necessary for an ASF release.

Please remember that publishing software has legal consequences.

This guide complements the foundation-wide policies and guides:

Some Terminology of release

In the context of our release, we use several terms to describe different stages of the release process.

Here's an explanation of these terms:

  • iceberg_version: the version of Iceberg to be released, like 0.2.0.
  • release_version: the version of release candidate, like 0.2.0-rc.1.
  • rc_version: the minor version for voting round, like rc.1.

Preparation

This section is the requirements for individuals who are new to the role of release manager.

Refer to Setup GPG Key to make sure the GPG key has been set up.

Start a tracking issue about the next release

Start a tracking issue on GitHub for the upcoming release to track all tasks that need to be completed.

Title:

Tracking issues of Iceberg Rust ${iceberg_version} Release

Content:

This issue is used to track tasks of the iceberg rust ${iceberg_version} release.

## Tasks

### Blockers

> Blockers are the tasks that must be completed before the release.

### Build Release

#### GitHub Side

- [ ] Bump version in project
- [ ] Update docs
- [ ] Generate dependencies list
- [ ] Push release candidate tag to GitHub

#### ASF Side

- [ ] Create an ASF Release
- [ ] Upload artifacts to the SVN dist repo

### Voting

- [ ] Start VOTE at iceberg community

### Official Release

- [ ] Push the release git tag
- [ ] Publish artifacts to SVN RELEASE branch
- [ ] Change Iceberg Rust Website download link
- [ ] Send the announcement

For details of each step, please refer to: https://rust.iceberg.apache.org/release

GitHub Side

Bump version in project

Bump all components' version in the project to the new iceberg version. Please note that this version is the exact version of the release, not the release candidate version.

  • rust core: bump version in Cargo.toml

Update docs

Generate dependencies list

Download and setup cargo-deny. You can refer to cargo-deny.

Running python3 ./scripts/dependencies.py generate to update the dependencies list of every package.

Push release candidate tag

After bump version PR gets merged, we can create a GitHub release for the release candidate:

  • Create a tag at main branch on the Bump Version / Patch up version commit: git tag -s "v0.2.0-rc.1", please correctly check out the corresponding commit instead of directly tagging on the main branch.
  • Push tags to GitHub: git push --tags.

ASF Side

If any step in the ASF Release process fails and requires code changes, we will abandon that version and prepare for the next one. Our release page will only display ASF releases instead of GitHub Releases.

Create an ASF Release

After GitHub Release has been created, we can start to create ASF Release.

  • Checkout to released tag. (e.g. git checkout v0.2.0-rc.1, tag is created in the previous step)
  • Use the release script to create a new release: ICEBERG_VERSION=<iceberg_version> ICEBERG_VERSION_RC=<rc_version> ./scripts/release.sh(e.g. ICEBERG_VERSION=0.2.0 ICEBERG_VERSION_RC=rc.1 ./scripts/release.sh)
    • This script will do the following things:
      • Create a new branch named by release-${release_version} from the tag
      • Generate the release candidate artifacts under dist, including:
        • apache-iceberg-rust-${release_version}-src.tar.gz
        • apache-iceberg-rust-${release_version}-src.tar.gz.asc
        • apache-iceberg-rust-${release_version}-src.tar.gz.sha512
      • Check the header of the source code. This step needs docker to run.
  • Push the newly created branch to GitHub

This script will create a new release under dist.

For example:

> tree dist
dist
├── apache-iceberg-rust-0.2.0-src.tar.gz
├── apache-iceberg-rust-0.2.0-src.tar.gz.asc
└── apache-iceberg-rust-0.2.0-src.tar.gz.sha512

Upload artifacts to the SVN dist repo

SVN is required for this step.

The svn repository of the dev branch is: https://dist.apache.org/repos/dist/dev/iceberg/iceberg-rust

First, checkout Iceberg to local directory:

# As this step will copy all the versions, it will take some time. If the network is broken, please use svn cleanup to delete the lock before re-execute it.
svn co https://dist.apache.org/repos/dist/dev/iceberg/ /tmp/iceberg-dist-dev

Then, upload the artifacts:

The ${release_version} here should be like 0.2.0-rc.1

# create a directory named by version
mkdir /tmp/iceberg-dist-dev/${release_version}
# copy source code and signature package to the versioned directory
cp ${repo_dir}/dist/* /tmp/iceberg-dist-dev/iceberg-rust-${release_version}/
# change dir to the svn folder
cd /tmp/iceberg-dist-dev/
# check svn status
svn status
# add to svn
svn add ${release_version}
# check svn status
svn status
# commit to SVN remote server
svn commit -m "Prepare for ${release_version}"

Visit https://dist.apache.org/repos/dist/dev/iceberg/iceberg-rust/ to make sure the artifacts are uploaded correctly.

Rescue

If you accidentally published wrong or unexpected artifacts, like wrong signature files, wrong sha256 files, please cancel the release for the current release_version, increase th RC counting and re-initiate a release with the new release_version. And remember to delete the wrong artifacts from the SVN dist repo.

Voting

Iceberg Community Vote should send email to: dev@iceberg.apache.org:

Title:

[VOTE] Release Apache Iceberg Rust ${release_version} RC1

Content:

Hello, Apache Iceberg Rust Community,

This is a call for a vote to release Apache Iceberg rust version ${iceberg_version}.

The tag to be voted on is ${iceberg_version}.

The release candidate:

https://dist.apache.org/repos/dist/dev/iceberg/iceberg-rust-${release_version}/

Keys to verify the release candidate:

https://downloads.apache.org/iceberg/KEYS

Git tag for the release:

https://github.com/apache/iceberg-rust/releases/tag/${release_version}

Please download, verify, and test.

The VOTE will be open for at least 72 hours and until the necessary
number of votes are reached.

[ ] +1 approve
[ ] +0 no opinion
[ ] -1 disapprove with the reason

To learn more about Apache Iceberg, please see https://rust.iceberg.apache.org/

Checklist for reference:

[ ] Download links are valid.
[ ] Checksums and signatures.
[ ] LICENSE/NOTICE files exist
[ ] No unexpected binary files
[ ] All source files have ASF headers
[ ] Can compile from source

More detailed checklist please refer to:
https://github.com/apache/iceberg-rust/tree/main/scripts

To compile from source, please refer to:
https://github.com/apache/iceberg-rust/blob/main/CONTRIBUTING.md

Here is a Python script in release to help you verify the release candidate:

./scripts/verify.py

Thanks

${name}

Example: https://lists.apache.org/thread/c211gqq2yl15jbxqk4rcnq1bdqltjm5l

After at least 3 +1 binding vote (from Iceberg PMC member), claim the vote result:

Title:

[RESULT][VOTE] Release Apache Iceberg Rust ${release_version} RC1

Content:

Hello, Apache Iceberg Rust Community,

The vote to release Apache Iceberg Rust ${release_version} has passed.

The vote PASSED with 3 +1 binding and 1 +1 non-binding votes, no +0 or -1 votes:

Binding votes:

- xxx
- yyy
- zzz

Non-Binding votes:

- aaa

Vote thread: ${vote_thread_url}

Thanks

${name}

Example: https://lists.apache.org/thread/xk5myl10mztcfotn59oo59s4ckvojds6

Official Release

Push the release git tag

# Checkout the tags that passed VOTE
git checkout ${release_version}
# Tag with the iceberg version
git tag -s ${iceberg_version}
# Push tags to github to trigger releases
git push origin ${iceberg_version}

Publish artifacts to SVN RELEASE branch

svn mv https://dist.apache.org/repos/dist/dev/iceberg/iceberg-rust/${release_version} https://dist.apache.org/repos/dist/release/iceberg/iceberg-rust/${iceberg_version} -m "Release ${iceberg_version}"

Update the download link in website/src/download.md to the new release version.

Create a GitHub Release

  • Click here to create a new release.
  • Pick the git tag of this release version from the dropdown menu.
  • Make sure the branch target is main.
  • Generate the release note by clicking the Generate release notes button.
  • Add the release note from every component's upgrade.md if there are breaking changes before the content generated by GitHub. Check them carefully.
  • Publish the release.

Send the announcement

Send the release announcement to dev@iceberg.apache.org and CC announce@apache.org.

Instead of adding breaking changes, let's include the new features as "notable changes" in the announcement.

Title:

[ANNOUNCE] Release Apache Iceberg Rust ${iceberg_version}

Content:

Hi all,

The Apache Iceberg Rust community is pleased to announce
that Apache Iceberg Rust ${iceberg_version} has been released!

Iceberg is a data access layer that allows users to easily and efficiently
retrieve data from various storage services in a unified way.

The notable changes since ${iceberg_version} include:
1. xxxxx
2. yyyyyy
3. zzzzzz

Please refer to the change log for the complete list of changes:
https://github.com/apache/iceberg-rust/releases/tag/v${iceberg_version}

Apache Iceberg Rust website: https://rust.iceberg.apache.org/

Download Links: https://rust.iceberg.apache.org/download

Iceberg Resources:
- Issue: https://github.com/apache/iceberg-rust/issues
- Mailing list: dev@iceberg.apache.org

Thanks
On behalf of Apache Iceberg Community

Example: https://lists.apache.org/thread/oy77n55brvk72tnlb2bjzfs9nz3cfd0s

Setup GPG key

This section is a brief from the Cryptography with OpenPGP guideline.

Install GPG

For more details, please refer to GPG official website. Here shows one approach to install GPG with apt:

sudo apt install gnupg2

Generate GPG Key

Attentions:

  • Name is best to keep consistent with your full name of Apache ID;
  • Email should be the Apache email;
  • Name is best to only use English to avoid garbled.

Run gpg --full-gen-key and complete the generation interactively:

gpg (GnuPG) 2.2.20; Copyright (C) 2020 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Please select what kind of key you want:
   (1) RSA and RSA (default)
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
  (14) Existing key from card
Your selection? 1 # input 1
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 4096 # input 4096
Requested keysize is 4096 bits
Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0) 0 # input 0
Key does not expire at all
Is this correct? (y/N) y # input y

GnuPG needs to construct a user ID to identify your key.

Real name: Hulk Lin               # input your name
Email address: hulk@apache.org    # input your email
Comment:                          # input some annotations, optional
You selected this USER-ID:
    "Hulk <hulk@apache.org>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O # input O
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.

# Input the security key
┌──────────────────────────────────────────────────────┐
│ Please enter this passphrase                         │
│                                                      │
│ Passphrase: _______________________________          │
│                                                      │
│       <OK>                              <Cancel>     │
└──────────────────────────────────────────────────────┘
# key generation will be done after your inputting the key with the following output
gpg: key E49B00F626B marked as ultimately trusted
gpg: revocation certificate stored as '/Users/hulk/.gnupg/openpgp-revocs.d/F77B887A4F25A9468C513E9AA3008E49B00F626B.rev'
public and secret key created and signed.

pub   rsa4096 2022-07-12 [SC]
      F77B887A4F25A9468C513E9AA3008E49B00F626B
uid           [ultimate] hulk <hulk@apache.org>
sub   rsa4096 2022-07-12 [E]

Upload your key to public GPG keyserver

Firstly, list your key:

gpg --list-keys

The output is like:

-------------------------------
pub   rsa4096 2022-07-12 [SC]
      F77B887A4F25A9468C513E9AA3008E49B00F626B
uid           [ultimate] hulk <hulk@apache.org>
sub   rsa4096 2022-07-12 [E]

Then, send your key id to key server:

gpg --keyserver keys.openpgp.org --send-key <key-id> # e.g., F77B887A4F25A9468C513E9AA3008E49B00F626B

Among them, keys.openpgp.org is a randomly selected keyserver, you can use keyserver.ubuntu.com or any other full-featured keyserver.

Check whether the key is created successfully

Uploading takes about one minute; after that, you can check by your email at the corresponding keyserver.

Uploading keys to the keyserver is mainly for joining a Web of Trust.

Add your GPG public key to the KEYS document

:::info

SVN is required for this step.

:::

The svn repository of the release branch is: https://dist.apache.org/repos/dist/release/iceberg

Please always add the public key to KEYS in the release branch:

svn co https://dist.apache.org/repos/dist/release/iceberg iceberg-dist
# As this step will copy all the versions, it will take some time. If the network is broken, please use svn cleanup to delete the lock before re-execute it.
cd iceberg-dist
(gpg --list-sigs YOUR_NAME@apache.org && gpg --export --armor YOUR_NAME@apache.org) >> KEYS # Append your key to the KEYS file
svn add .   # It is not needed if the KEYS document exists before.
svn ci -m "add gpg key for YOUR_NAME" # Later on, if you are asked to enter a username and password, just use your apache username and password.

Upload the GPG public key to your GitHub account

  • Enter https://github.com/settings/keys to add your GPG key.
  • Please remember to bind the email address used in the GPG key to your GitHub account (https://github.com/settings/emails) if you find "unverified" after adding it.