This is an automated email from the ASF dual-hosted git repository.

penghui pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pulsar.git


The following commit(s) were added to refs/heads/master by this push:
     new 3ecf34abf99 Move Pulsar release related docs to codebase (#17176)
3ecf34abf99 is described below

commit 3ecf34abf99afd7c53a681ab82d5bcec2bc499a1
Author: Penghui Li <[email protected]>
AuthorDate: Fri Aug 19 16:54:14 2022 +0800

    Move Pulsar release related docs to codebase (#17176)
---
 wiki/release/create-gpg-keys.md              | 163 +++++++
 wiki/release/release-candidate-validation.md | 611 +++++++++++++++++++++++++++
 wiki/release/release-process.md              | 599 ++++++++++++++++++++++++++
 3 files changed, 1373 insertions(+)

diff --git a/wiki/release/create-gpg-keys.md b/wiki/release/create-gpg-keys.md
new file mode 100644
index 00000000000..66d467a1f22
--- /dev/null
+++ b/wiki/release/create-gpg-keys.md
@@ -0,0 +1,163 @@
+<!--
+
+    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.
+
+-->
+
+# Create GPG keys to sign release artifacts
+
+This page provides instructions for Pulsar committers on how to do
+the initial gpg setup.
+
+This is a condensed version of instructions available at
+http://apache.org/dev/openpgp.html.
+
+
+Install GnuPG. For example on MacOS:
+
+```shell
+brew install gnupg
+```
+
+Set configuration to use `SHA512` keys by default.
+
+```shell
+mkdir ~/.gnupg
+cat <<EOL >> ~/.gnupg/gpg.conf
+personal-digest-preferences SHA512
+cert-digest-algo SHA512
+default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 
ZLIB BZIP2 ZIP Uncompressed
+EOL
+chmod 700 ~/.gnupg/gpg.conf
+```
+
+Check the version.
+
+```shell
+gpg --version
+
+gpg (GnuPG) 2.1.22
+libgcrypt 1.8.0
+Copyright (C) 2017 Free Software Foundation, Inc.
+License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>
+This is free software: you are free to change and redistribute it.
+There is NO WARRANTY, to the extent permitted by law.
+
+Home: /Users/nkurihar/.gnupg
+Supported algorithms:
+Pubkey: RSA, ELG, DSA, ECDH, ECDSA, EDDSA
+Cipher: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH,
+        CAMELLIA128, CAMELLIA192, CAMELLIA256
+Hash: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
+Compression: Uncompressed, ZIP, ZLIB, BZIP2
+```
+
+Generate new GPG key.
+Note that new **RSA** keys generated should be at least **4096** bits.
+
+```shell
+# For 1.x or 2.0.x
+gpg --gen-key
+
+# For 2.1.x
+gpg --full-gen-key
+
+gpg (GnuPG) 2.1.22; Copyright (C) 2017 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)
+Your selection? 1
+RSA keys may be between 1024 and 4096 bits long.
+What keysize do you want? (2048) 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
+Key does not expire at all
+Is this correct? (y/N) y
+                        
+GnuPG needs to construct a user ID to identify your key.
+
+Real name: test user
+Email address: [email protected]
+Comment: CODE SIGNING KEY     
+You selected this USER-ID:
+    "test user (CODE SIGNING KEY) <[email protected]>"
+
+Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O
+<Enter passphrase>
+```
+
+#### Appending the key to KEYS files
+
+The GPG key needs to be appended to `KEYS` file that is stored in 2 SVN 
locations,
+one for proper releases and one for the release candidates.
+
+The credentials for SVN are the usual Apache account credentials.
+
+```shell
+# Checkout the SVN folder containing the KEYS file
+svn co https://dist.apache.org/repos/dist/dev/pulsar pulsar-dist-dev-keys 
--depth empty
+cd pulsar-dist-dev-keys
+svn up KEYS
+
+APACHEID=apacheid
+# Export the key in ascii format and append it to the file
+( gpg --list-sigs [email protected]
+  gpg --export --armor [email protected] ) >> KEYS
+
+# Commit to SVN
+svn ci -m "Added gpg key for $APACHEID"
+```
+
+Repeat the same operation for the release KEYS file:
+
+> :warning: You should ask a PMC member to complete this step.
+
+```shell
+# Checkout the SVN folder containing the KEYS file
+svn co https://dist.apache.org/repos/dist/release/pulsar 
pulsar-dist-release-keys --depth empty
+cd pulsar-dist-release-keys
+svn up KEYS
+
+APACHEID=apacheid
+# Export the key in ascii format and append it to the file
+( gpg --list-sigs [email protected]
+  gpg --export --armor [email protected] ) >> KEYS
+
+# Commit to SVN
+svn ci -m "Added gpg key for $APACHEID"
+```
+
+#### Upload the key to a public key server
+
+Use the key id to publish it to several public key servers:
+```shell
+gpg --send-key 8C75C738C33372AE198FD10CC238A8CAAC055FD2
+gpg --send-key --keyserver=keys.openpgp.org 
8C75C738C33372AE198FD10CC238A8CAAC055FD2
+gpg --send-key --keyserver=keyserver.ubuntu.com 
8C75C738C33372AE198FD10CC238A8CAAC055FD2
+```
\ No newline at end of file
diff --git a/wiki/release/release-candidate-validation.md 
b/wiki/release/release-candidate-validation.md
new file mode 100644
index 00000000000..082cc466da8
--- /dev/null
+++ b/wiki/release/release-candidate-validation.md
@@ -0,0 +1,611 @@
+<!--
+
+    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.
+
+-->
+
+# Release Candidate Validation
+
+- [Validate Binary Distribution](#validate-the-binary-distribution)
+    * [Download And Verify Binary 
Distributions](#download-the-binary-distributions)
+    * [Validate Pub/Sub and Java 
Functions](#validate-pubsub-and-java-functions)
+    * [Validate Connectors](#validate-connectors)
+    * [Validate Stateful Functions](#validate-stateful-functions)
+
+The following are manual instructions for reviewing and validating a release 
candidate.
+You can automate these steps. Contributions are welcome!
+
+## Validate the binary distribution
+
+### Download And Verify the binary distributions
+
+Download the server distribution `apache-pulsar-<release>-bin.tar.gz` and 
extract it. The extracted files are in a directory called 
`apache-pulsar-<release>`. All the operations below happen within that 
directory.
+
+```shell
+$ cd apache-pulsar-<release>
+$ mkdir connectors
+```
+
+Download the Pulsar IO Connector files
+```
+pulsar-io-aerospike-<release>.nar
+pulsar-io-cassandra-<release>.nar
+pulsar-io-kafka-<release>.nar
+pulsar-io-kinesis-<release>.nar
+pulsar-io-rabbitmq-<release>.nar
+pulsar-io-twitter-<release>.nar
+```
+and place them in the `connectors` directory.
+
+Download the `*.asc` file and verify the GPG signature
+
+```bash
+gpg verify apache-pulsar-<release>-bin.tar.gz.asc
+```
+
+### Validate Pub/Sub and Java Functions
+
+1. Open a terminal to start a standalone cluster.
+
+```shell
+$ bin/pulsar standalone
+```
+
+When you start a standalone cluster, there are a few things to check.
+
+a) The standalone cluster is able to locate all the connectors. The following 
logging information should be displayed.
+
+```shell
+Found connector ConnectorDefinition(name=kinesis, description=Kinesis sink 
connector, sourceClass=null, 
sinkClass=org.apache.pulsar.io.kinesis.KinesisSink) from 
/Users/sijie/tmp/apache-pulsar-2.1.0-incubating/./connectors/pulsar-io-kinesis-2.1.0-incubating.nar
+...
+Found connector ConnectorDefinition(name=cassandra, description=Writes data 
into Cassandra, sourceClass=null, 
sinkClass=org.apache.pulsar.io.cassandra.CassandraStringSink) from 
/Users/sijie/tmp/apache-pulsar-2.1.0-incubating/./connectors/pulsar-io-cassandra-2.1.0-incubating.nar
+...
+Found connector ConnectorDefinition(name=aerospike, description=Aerospike 
database sink, sourceClass=null, 
sinkClass=org.apache.pulsar.io.aerospike.AerospikeStringSink) from 
/Users/sijie/tmp/apache-pulsar-2.1.0-incubating/./connectors/pulsar-io-aerospike-2.1.0-incubating.nar
+```
+
+b) (since Pulsar 2.1 release) The standalone starts bookkeeper table service. 
The output is similar as follows:
+
+```shell
+12:12:26.099 [main] INFO  org.apache.pulsar.zookeeper.LocalBookkeeperEnsemble 
- 'default' namespace for table service : namespace_name: "default"
+default_stream_conf {
+  key_type: HASH
+  min_num_ranges: 24
+  initial_num_ranges: 24
+  split_policy {
+    fixed_range_policy {
+      num_ranges: 2
+    }
+  }
+  rolling_policy {
+    size_policy {
+      max_segment_size: 134217728
+    }
+  }
+  retention_policy {
+    time_policy {
+      retention_minutes: -1
+    }
+  }
+}
+```
+
+c) Functions worker is started correctly. The output is similar as follows:
+
+```shell
+14:28:24.101 [main] INFO  org.apache.pulsar.functions.worker.WorkerService - 
Starting worker c-standalone-fw-localhost-8080...
+14:28:24.907 [main] INFO  org.apache.pulsar.functions.worker.WorkerService - 
Worker Configs: {
+  "workerId" : "c-standalone-fw-localhost-8080",
+  "workerHostname" : "localhost",
+  "workerPort" : 8080,
+  "workerPortTls" : 6751,
+  "jvmGCMetricsLoggerClassName" : null,
+  "numHttpServerThreads" : 8,
+  "connectorsDirectory" : "./connectors",
+  "functionMetadataTopicName" : "metadata",
+  "functionWebServiceUrl" : null,
+  "pulsarServiceUrl" : "pulsar://127.0.0.1:6650",
+  "pulsarWebServiceUrl" : "http://127.0.0.1:8080";,
+  "clusterCoordinationTopicName" : "coordinate",
+  "pulsarFunctionsNamespace" : "public/functions",
+  "pulsarFunctionsCluster" : "standalone",
+  "numFunctionPackageReplicas" : 1,
+  "downloadDirectory" : "/tmp/pulsar_functions",
+  "stateStorageServiceUrl" : "bk://127.0.0.1:4181",
+  "functionAssignmentTopicName" : "assignments",
+  "schedulerClassName" : 
"org.apache.pulsar.functions.worker.scheduler.RoundRobinScheduler",
+  "failureCheckFreqMs" : 30000,
+  "rescheduleTimeoutMs" : 60000,
+  "initialBrokerReconnectMaxRetries" : 60,
+  "assignmentWriteMaxRetries" : 60,
+  "instanceLivenessCheckFreqMs" : 30000,
+  "clientAuthenticationPlugin" : null,
+  "clientAuthenticationParameters" : null,
+  "topicCompactionFrequencySec" : 1800,
+  "tlsEnabled" : true,
+  "tlsCertificateFilePath" : null,
+  "tlsKeyFilePath" : null,
+  "tlsTrustCertsFilePath" : null,
+  "tlsAllowInsecureConnection" : false,
+  "tlsRequireTrustedClientCertOnConnect" : false,
+  "useTls" : false,
+  "tlsHostnameVerificationEnable" : false,
+  "authenticationEnabled" : false,
+  "authenticationProviders" : null,
+  "authorizationEnabled" : false,
+  "superUserRoles" : null,
+  "properties" : { },
+  "threadContainerFactory" : null,
+  "processContainerFactory" : {
+    "javaInstanceJarLocation" : null,
+    "pythonInstanceLocation" : null,
+    "logDirectory" : null,
+    "extraFunctionDependenciesDir" : null
+  },
+  "kubernetesContainerFactory" : null,
+  "secretsProviderConfiguratorClassName" : null,
+  "secretsProviderConfiguratorConfig" : null,
+  "functionInstanceMinResources" : null,
+  "workerWebAddress" : "http://localhost:8080";,
+  "functionMetadataTopic" : "persistent://public/functions/metadata",
+  "clusterCoordinationTopic" : "persistent://public/functions/coordinate",
+  "functionAssignmentTopic" : "persistent://public/functions/assignments"
+}
+```
+
+d) Do sanity check before moving to the next step.
+
+```shell
+// check pulsar binary port is listened correctly
+$ netstat -an | grep 6650 | grep LISTEN
+
+// check function cluster
+$ curl -s http://localhost:8080/admin/v2/worker/cluster
+// example output
+[{"workerId":"c-standalone-fw-localhost-6750","workerHostname":"localhost","port":6750}]
+
+// check brokers
+$ curl -s http://localhost:8080/admin/v2/namespaces/public
+// example outoupt
+["public/default","public/functions"]
+
+// check connectors
+$ curl -s http://localhost:8080/admin/v2/functions/connectors
+// example output
+[{"name":"aerospike","description":"Aerospike database 
sink","sinkClass":"org.apache.pulsar.io.aerospike.AerospikeStringSink"},{"name":"cassandra","description":"Writes
 data into 
Cassandra","sinkClass":"org.apache.pulsar.io.cassandra.CassandraStringSink"},{"name":"kafka","description":"Kafka
 source and sink 
connector","sourceClass":"org.apache.pulsar.io.kafka.KafkaStringSource","sinkClass":"org.apache.pulsar.io.kafka.KafkaStringSink"},{"name":"kinesis","description":"Kinesis
 sink connect [...]
+
+// check table services
+$ nc -vz4 localhost 4181
+```
+
+2. Open another terminal to submit a Java Exclamation function.
+
+a) Create tenant and namespace.
+
+```shell
+$ bin/pulsar-admin tenants create test
+$ bin/pulsar-admin namespaces create test/test-namespace
+```
+
+b) Create function.
+
+```shell
+$ bin/pulsar-admin functions create --function-config-file 
examples/example-function-config.yaml --jar examples/api-examples.jar
+```
+
+The following information is returned.
+`Created Successfully`
+
+3. At the same terminal as step 2, retrieve the function configuration.
+
+```shell
+$ bin/pulsar-admin functions get --tenant test --namespace test-namespace 
--name example
+```
+
+The output is similar as follows:
+
+```shell
+{
+  "tenant": "test",
+  "namespace": "test-namespace",
+  "name": "example",
+  "className": "org.apache.pulsar.functions.api.examples.ExclamationFunction",
+  "userConfig": "{\"PublishTopic\":\"test_result\"}",
+  "autoAck": true,
+  "parallelism": 1,
+  "source": {
+    "topicsToSerDeClassName": {
+      "test_src": ""
+    },
+    "typeClassName": "java.lang.String"
+  },
+  "sink": {
+    "topic": "test_result",
+    "typeClassName": "java.lang.String"
+  },
+  "resources": {}
+}
+```
+
+4. At the same terminal as step 3, retrieve the function status.
+
+```shell
+$ bin/pulsar-admin functions status --tenant test --namespace test-namespace 
--name example
+```
+The output is similar as follows:
+
+```shell
+{
+  "numInstances" : 1,
+  "numRunning" : 1,
+  "instances" : [ {
+    "instanceId" : 0,
+    "status" : {
+      "running" : true,
+      "error" : "",
+      "numRestarts" : 0,
+      "numReceived" : 0,
+      "numSuccessfullyProcessed" : 0,
+      "numUserExceptions" : 0,
+      "latestUserExceptions" : [ ],
+      "numSystemExceptions" : 0,
+      "latestSystemExceptions" : [ ],
+      "averageLatency" : 0.0,
+      "lastInvocationTime" : 0,
+      "workerId" : "c-standalone-fw-localhost-8080"
+    }
+  } ]
+}
+```
+
+5. At the same terminal as step 4, subscribe the output topic `test_result`.
+
+```shell
+$ bin/pulsar-client consume -s test-sub -n 0 test_result
+```
+
+6. Open a new terminal to produce messages into the input topic `test_src`.
+
+```shell
+$ bin/pulsar-client produce -m "test-messages-`date`" -n 10 test_src
+```
+
+7. At the terminal of step 5, the messages produced by the Exclamation 
function is returned. The output is similar as follows:
+
+```shell
+----- got message -----
+test-messages-Thu Jul 19 11:59:15 PDT 2018!
+----- got message -----
+test-messages-Thu Jul 19 11:59:15 PDT 2018!
+----- got message -----
+test-messages-Thu Jul 19 11:59:15 PDT 2018!
+----- got message -----
+test-messages-Thu Jul 19 11:59:15 PDT 2018!
+----- got message -----
+test-messages-Thu Jul 19 11:59:15 PDT 2018!
+----- got message -----
+test-messages-Thu Jul 19 11:59:15 PDT 2018!
+----- got message -----
+test-messages-Thu Jul 19 11:59:15 PDT 2018!
+----- got message -----
+test-messages-Thu Jul 19 11:59:15 PDT 2018!
+----- got message -----
+test-messages-Thu Jul 19 11:59:15 PDT 2018!
+----- got message -----
+test-messages-Thu Jul 19 11:59:15 PDT 2018!
+```
+
+### Validate Connectors
+
+> Make sure you have docker available at your laptop. If you haven't installed 
docker, you can skip this section.
+
+1. Set up a cassandra cluster.
+
+```shell
+$ docker run -d --rm  --name=cassandra -p 9042:9042 cassandra
+```
+
+Make sure that the cassandra cluster is running.
+
+```shell
+// run docker ps to find the docker process for cassandra
+$ docker ps
+```
+
+```shell
+// check if the cassandra is running as expected
+$ docker logs cassandra
+```
+
+```shell
+// check the cluster status
+$ docker exec cassandra nodetool status
+Datacenter: datacenter1
+=======================
+Status=Up/Down
+|/ State=Normal/Leaving/Joining/Moving
+--  Address     Load       Tokens       Owns (effective)  Host ID              
                 Rack
+UN  172.17.0.2  103.67 KiB  256          100.0%            
af0e4b2f-84e0-4f0b-bb14-bd5f9070ff26  rack1
+```
+
+2. Create keyspace and table.
+
+Run cqlsh:
+```shell
+$ docker exec -ti cassandra cqlsh localhost
+Connected to Test Cluster at localhost:9042.
+[cqlsh 5.0.1 | Cassandra 3.11.2 | CQL spec 3.4.4 | Native protocol v4]
+Use HELP for help.
+cqlsh>
+```
+
+In the cqlsh, create the `pulsar_test_keyspace` keyspace and the 
`pulsar_test_table` table.
+
+```shell
+cqlsh> CREATE KEYSPACE pulsar_test_keyspace WITH replication = 
{'class':'SimpleStrategy', 'replication_factor':1};
+cqlsh> USE pulsar_test_keyspace;
+cqlsh:pulsar_test_keyspace> CREATE TABLE pulsar_test_table (key text PRIMARY 
KEY, col text);
+
+```
+
+3. Prepare a cassandra sink yaml file and put it under examples directory as 
`cassandra-sink.yml`.
+
+```shell
+$ cat examples/cassandra-sink.yml
+configs:
+    roots: "localhost:9042"
+    keyspace: "pulsar_test_keyspace"
+    columnFamily: "pulsar_test_table"
+    keyname: "key"
+    columnName: "col"
+```
+
+4. Submit a cassandra sink.
+
+```shell
+$ bin/pulsar-admin sink create --tenant public --namespace default --name 
cassandra-test-sink --sink-type cassandra --sink-config-file 
examples/cassandra-sink.yml --inputs test_cassandra
+"Created successfully"
+```
+
+```shell
+// get the sink info
+$ bin/pulsar-admin sink get --tenant public --namespace default --name 
cassandra-test-sink
+{
+  "tenant": "public",
+  "namespace": "default",
+  "name": "cassandra-test-sink",
+  "className": "org.apache.pulsar.io.cassandra.CassandraStringSink",
+  "inputSpecs": {
+    "test_cassandra": {
+      "isRegexPattern": false
+    }
+  },
+  "configs": {
+    "roots": "localhost:9042",
+    "keyspace": "pulsar_test_keyspace",
+    "columnFamily": "pulsar_test_table",
+    "keyname": "key",
+    "columnName": "col"
+  },
+  "parallelism": 1,
+  "processingGuarantees": "ATLEAST_ONCE",
+  "retainOrdering": false,
+  "autoAck": true,
+  "archive": "builtin://cassandra"
+}
+```
+
+```shell
+// get the running status
+$ bin/pulsar-admin sink status --tenant public --namespace default --name 
cassandra-test-sink
+{
+  "numInstances" : 1,
+  "numRunning" : 1,
+  "instances" : [ {
+    "instanceId" : 0,
+    "status" : {
+      "running" : true,
+      "error" : "",
+      "numRestarts" : 0,
+      "numReadFromPulsar" : 0,
+      "numSystemExceptions" : 0,
+      "latestSystemExceptions" : [ ],
+      "numSinkExceptions" : 0,
+      "latestSinkExceptions" : [ ],
+      "numWrittenToSink" : 0,
+      "lastReceivedTime" : 0,
+      "workerId" : "c-standalone-fw-localhost-8080"
+    }
+  } ]
+}
+```
+
+5. Produce messages to the source topic.
+```shell
+$ for i in {0..10}; do bin/pulsar-client produce -m "key-$i" -n 1 
test_cassandra; done
+```
+
+6. Check the sink status, and 11 messages are processed.
+
+```shell
+$ bin/pulsar-admin sink status --tenant public --namespace default --name 
cassandra-test-sink
+{
+  "numInstances" : 1,
+  "numRunning" : 1,
+  "instances" : [ {
+    "instanceId" : 0,
+    "status" : {
+      "running" : true,
+      "error" : "",
+      "numRestarts" : 0,
+      "numReadFromPulsar" : 11,
+      "numSystemExceptions" : 0,
+      "latestSystemExceptions" : [ ],
+      "numSinkExceptions" : 0,
+      "latestSinkExceptions" : [ ],
+      "numWrittenToSink" : 11,
+      "lastReceivedTime" : 1554833501277,
+      "workerId" : "c-standalone-fw-localhost-8080"
+    }
+  } ]
+}
+```
+
+7. Check results in cassandra.
+
+```shell
+$ docker exec -ti cassandra cqlsh localhost
+Connected to Test Cluster at localhost:9042.
+[cqlsh 5.0.1 | Cassandra 3.11.2 | CQL spec 3.4.4 | Native protocol v4]
+Use HELP for help.
+cqlsh> use pulsar_test_keyspace;
+cqlsh:pulsar_test_keyspace> select * from pulsar_test_table;
+
+ key    | col
+--------+--------
+  key-5 |  key-5
+  key-0 |  key-0
+  key-9 |  key-9
+  key-2 |  key-2
+  key-1 |  key-1
+  key-3 |  key-3
+  key-6 |  key-6
+  key-7 |  key-7
+  key-4 |  key-4
+  key-8 |  key-8
+ key-10 | key-10
+
+(11 rows)
+```
+
+8. Delete the sink.
+
+```shell
+$ bin/pulsar-admin sink delete --tenant public --namespace default --name 
cassandra-test-sink
+"Deleted successfully"
+```
+
+### Validate Stateful Functions
+
+Since Pulsar 2.1 release, Pulsar enables bookkeeper table service for stateful 
Pulsar functions (as a developer preview).
+
+The following are instructions to validate counter functions.
+
+1. Create a wordcount function.
+
+```shell
+$ bin/pulsar-admin functions create --function-config-file 
examples/example-function-config.yaml --jar examples/api-examples.jar --name 
word_count --className 
org.apache.pulsar.functions.api.examples.WordCountFunction --inputs 
test_wordcount_src --output test_wordcount_dest
+"Created successfully"
+```
+
+2. Get function information and status.
+
+```shell
+$ bin/pulsar-admin functions get --tenant test --namespace test-namespace 
--name word_count
+{
+  "tenant": "test",
+  "namespace": "test-namespace",
+  "name": "word_count",
+  "className": "org.apache.pulsar.functions.api.examples.WordCountFunction",
+  "inputSpecs": {
+    "test_wordcount_src": {
+      "isRegexPattern": false
+    }
+  },
+  "output": "test_wordcount_dest",
+  "processingGuarantees": "ATLEAST_ONCE",
+  "retainOrdering": false,
+  "userConfig": {
+    "PublishTopic": "test_result"
+  },
+  "runtime": "JAVA",
+  "autoAck": true,
+  "parallelism": 1,
+  "resources": {
+    "cpu": 1.0,
+    "ram": 1073741824,
+    "disk": 10737418240
+  },
+  "cleanupSubscription": true
+}
+```
+
+```shell
+$ bin/pulsar-admin functions status --tenant test --namespace test-namespace 
--name word_count
+{
+  "numInstances" : 1,
+  "numRunning" : 1,
+  "instances" : [ {
+    "instanceId" : 0,
+    "status" : {
+      "running" : true,
+      "error" : "",
+      "numRestarts" : 0,
+      "numReceived" : 0,
+      "numSuccessfullyProcessed" : 0,
+      "numUserExceptions" : 0,
+      "latestUserExceptions" : [ ],
+      "numSystemExceptions" : 0,
+      "latestSystemExceptions" : [ ],
+      "averageLatency" : 0.0,
+      "lastInvocationTime" : 0,
+      "workerId" : "c-standalone-fw-localhost-8080"
+    }
+  } ]
+}
+```
+
+3. Query the state table for the function: watching on a key called "hello"
+
+```shell
+$ bin/pulsar-admin functions querystate --tenant test --namespace 
test-namespace --name word_count -k hello -w
+key 'hello' doesn't exist.
+key 'hello' doesn't exist.
+key 'hello' doesn't exist
+```
+
+4. Produce the messages to source topic `test_wordcount_src`.
+
+Produce 10 messages "hello" to the `test_wordcount_src` topic. The value of 
"hello" is updated to 10.
+
+```shell
+$ bin/pulsar-client produce -m "hello" -n 10 test_wordcount_src
+```
+
+Checkout the result in the terminal of step 3.
+
+```shell
+{
+  "key": "hello",
+  "numberValue": 10,
+  "version": 9
+}
+```
+
+Produce another 10 messages "hello". The result is updated to 20.
+
+```shell
+$ bin/pulsar-client produce -m "hello" -n 10 test_wordcount_src
+```
+
+The result in the terminal of step 3 is updated to `20`.
+
+```shell
+  "key": "hello",
+  "numberValue": 20,
+  "version": 19
+```
diff --git a/wiki/release/release-process.md b/wiki/release/release-process.md
new file mode 100644
index 00000000000..ad40b38e05c
--- /dev/null
+++ b/wiki/release/release-process.md
@@ -0,0 +1,599 @@
+<!--
+
+    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.
+
+-->
+
+# Release Process
+
+
+This page contains instructions for Pulsar committers on how to perform a 
release.
+
+If you haven't already done it, [create and publish the GPG 
key](https://github.com/apache/pulsar/wiki/Create-GPG-keys-to-sign-release-artifacts)
 to sign the release artifacts.
+
+Before you start the next release steps, make sure you have installed the 
**JDK8** and maven **3.6.1** for Pulsar 2.6 and Pulsar 2.7, and **JDK11** and 
Maven **3.6.1** for Pulsar 2.8 onwards. And **clean up the bookkeeper's local 
compiled** to make sure the bookkeeper dependency is fetched from the Maven 
repo, details to see 
https://lists.apache.org/thread/gsbh95b2d9xtcg5fmtxpm9k9q6w68gd2
+
+## Release workflow
+
+The steps for releasing are as follows:
+1. Create release branch
+2. Update project version and tag
+3. Build and inspect the artifacts
+4. Inspect the artifacts
+5. Stage artifacts in maven
+6. Move master branch to next version
+7. Write release notes
+8. Run the vote
+19. Promote the release
+10. Publish Docker Images
+11. Publish Python
+12. Publish MacOS `libpulsar` package
+13. Generate Python Client docs
+14. Update swagger file
+15. Update release notes
+16. Update the site
+17. Announce the release
+18. Write a blog post for the release (optional)
+19. Remove old releases
+20. Move branch to next version
+
+The following are details for each step.
+
+## 1. Create the release branch
+
+We are going to create a branch from `master` to `branch-v2.X`
+where the tag will be generated and where new fixes will be
+applied as part of the maintenance for the release.
+
+The branch needs only to be created when creating major releases,
+and not for patch releases like `2.3.1`. For patch and minor release, goto 
next step.
+
+Eg: When creating `v2.3.0` release, the branch `branch-2.3` will be created; 
but for `v2.3.1`, we
+keep using the old `branch-2.3`.
+
+In these instructions, I'm referring to a fictitious release `2.X.0`. Change 
the release version in the examples accordingly with the real version.
+
+It is recommended to create a fresh clone of the repository to avoid any local 
files to interfere
+in the process:
+
+```shell
+git clone [email protected]:apache/pulsar.git
+cd pulsar
+git checkout -b branch-2.X origin/master
+```
+
+Alternatively, you can use a git workspace to create a new, clean directory on 
your machine without needing to re-download the project.
+
+```shell
+git worktree add ../pulsar.branch-2.X branch-2.X
+```
+
+If you created a new branch, update the `CI - OWASP Dependency Check` workflow 
so that it will run on the new branch. At the time of writing, here is the file 
that should be updated: 
https://github.com/apache/pulsar/blob/master/.github/workflows/ci-owasp-dependency-check.yaml.
+
+(Note also that we should stop the GitHub action for Pulsar versions that are 
EOL.)
+
+Also, if you created a new branch, please update the `Security Policy and 
Supported Versions` page on the website. This page has a table for support 
timelines based on when minor releases take place.
+
+## 2. Update project version and tag
+
+During the release process, we are going to initially create
+"candidate" tags, that after verification and approval will
+get promoted to the "real" final tag.
+
+In this process the maven version of the project will always
+be the final one.
+
+```shell
+# Bump to the release version
+./src/set-project-version.sh 2.X.0
+
+# Some version may not update the right parent version of 
`protobuf-shaded/pom.xml`, please double check it.
+
+# Commit
+git commit -m 'Release 2.X.0' -a
+
+# Create a "candidate" tag
+# If you don't sign your commits already, use the following
+export GPG_TTY=$(tty)
+git tag -u [email protected] v2.X.0-candidate-1 -m 'Release v2.X.0-candidate-1'
+# If you already sign your commits using your apache.org email, use the 
following
+git tag -s v2.X.0-candidate-1 -m 'Release v2.X.0-candidate-1'
+
+# Verify that you signed your tag before pushing it:
+git tag -v v2.X.0-candidate-1
+
+# Push both the branch and the tag to Github repo
+git push origin branch-2.X
+git push origin v2.X.0-candidate-1
+```
+
+For minor release, tag is like `2.3.1`.
+
+## 3. Build and inspect the artifacts
+
+```shell
+mvn clean install -DskipTests
+```
+
+After the build, there will be 4 generated artifacts:
+
+* `distribution/server/target/apache-pulsar-2.X.0-bin.tar.gz`
+* `target/apache-pulsar-2.X.0-src.tar.gz`
+* `distribution/offloaders/target/apache-pulsar-offloaders-2.X.0-bin.tar.gz`
+* directory `distribution/io/target/apache-pulsar-io-connectors-2.x.0-bin` 
contains all io connect nars
+
+Inspect the artifacts:
+* Check that the `LICENSE` and `NOTICE` files cover all included jars for the 
-bin package)
+    - Use script to cross-validate `LICENSE` file with included jars:
+       ```
+       src/check-binary-license 
distribution/server/target/apache-pulsar-2.x.0-bin.tar.gz
+       ```
+* Unpack src package: `target/apache-pulsar-2.X.0-src.tar.gz`
+    - Run Apache RAT to verify the license headers in the `src` package:
+       ```shell
+       cd apache-pulsar-2.X.0
+       mvn apache-rat:check
+       ```
+* Unpack bin package: 
`distribution/server/target/apache-pulsar-2.X.0-bin.tar.gz`, Check that the 
standalone Pulsar service starts correctly:
+ ```shell
+ cd apache-pulsar-2.X.0
+ bin/pulsar standalone
+ ```
+
+* Use instructions in 
[Release-Candidate-Validation](Release-Candidate-Validation) to do some sanity 
checks on the produced binary distributions.
+
+### 3.1. Build RPM and DEB packages
+
+```shell
+pulsar-client-cpp/pkg/rpm/docker-build-rpm.sh
+
+pulsar-client-cpp/pkg/deb/docker-build-deb.sh
+```
+
+> For 2.11.0 or higher, you can set the environment variable `BUILD_IMAGE` to 
build the base image locally instead of pulling from the DockerHub.
+> Since only a few members have the permission to push the image to DockerHub, 
the image might not be the latest, if you failed to build the RPM and DEB 
packages, you can run `export BUILD_IMAGE=1` before running these commands.
+
+This will leave the RPM/YUM and DEB repo files in 
`pulsar-client-cpp/pkg/rpm/RPMS/x86_64` and
+`pulsar-client-cpp/pkg/deb/BUILD/DEB` directory.
+
+> Tips: If you get error `c++: internal compiler error: Killed (program 
cc1plus)` when run `pulsar-client-cpp/pkg/deb/docker-build-deb.sh`. You may 
need to expand your docker memory greater than 2GB.
+
+## 4. Sign and stage the artifacts
+
+The `src` and `bin` artifacts need to be signed and uploaded to the dist SVN
+repository for staging.
+
+Before running the script, make sure that the `[email protected]` code signing 
key is the default gpg signing key.
+One way to ensure this is to create/edit file `~/.gnupg/gpg.conf` and add a 
line
+```
+default-key <key fingerprint>
+```
+where `<key fingerprint>` should be replaced with the private key fingerprint 
for the `[email protected]` key. The key fingerprint can be found in `gpg -K` 
output.
+
+```shell
+svn co https://dist.apache.org/repos/dist/dev/pulsar pulsar-dist-dev
+cd pulsar-dist-dev
+
+# '-candidate-1' needs to be incremented in case of multiple iteration in 
getting
+#    to the final release)
+svn mkdir pulsar-2.X.0-candidate-1
+
+cd pulsar-2.X.0-candidate-1
+$PULSAR_PATH/src/stage-release.sh .
+
+svn add *
+svn ci -m 'Staging artifacts and signature for Pulsar release 2.X.0'
+```
+
+## 5. Stage artifacts in maven
+
+Upload the artifacts to ASF Nexus:
+
+```shell
+
+# remove CPP client binaries (they would file the license/RAT check in 
"deploy")
+cd pulsar-client-cpp
+git clean -xfd
+cd ..
+
+export APACHE_USER=$USER
+export APACHE_PASSWORD=$MY_PASSWORD
+export GPG_TTY=$(tty)
+# src/settings.xml from master branch to /tmp/mvn-apache-settings.xml since 
it's missing in some branches
+curl -s -o /tmp/mvn-apache-settings.xml 
https://raw.githubusercontent.com/apache/pulsar/master/src/settings.xml
+# publish artifacts
+mvn deploy -DskipTests -Papache-release --settings /tmp/mvn-apache-settings.xml
+# publish org.apache.pulsar.tests:integration and it's parent pom 
org.apache.pulsar.tests:tests-parent
+mvn deploy -DskipTests -Papache-release --settings 
/tmp/mvn-apache-settings.xml -f tests/pom.xml -pl 
org.apache.pulsar.tests:tests-parent,org.apache.pulsar.tests:integration
+```
+
+This will ask for the GPG key passphrase and then upload to the staging 
repository.
+
+> If you have deployed before, re-deploying might fail on 
pulsar-presto-connector-original.
+>
+> See https://github.com/apache/pulsar/issues/17047.
+>
+> You can run `mvn clean deploy` instead of `mvn deploy` as a workaround.
+
+Login to ASF Nexus repository at https://repository.apache.org
+
+Click on "Staging Repositories" on the left sidebar and then select the current
+Pulsar staging repo. This should be called something like 
`orgapachepulsar-XYZ`.
+
+Use the "Close" button to close the repository. This operation will take few
+minutes. Once complete click "Refresh" and now a link to the staging repository
+should be available, something like
+https://repository.apache.org/content/repositories/orgapachepulsar-XYZ
+
+
+## 6. Move master branch to next version
+
+We need to move master version to next iteration `X + 1`.
+
+```
+git checkout master
+./src/set-project-version.sh 2.Y.0-SNAPSHOT
+
+git commit -m 'Bumped version to 2.Y.0-SNAPSHOT' -a
+```
+
+Since this needs to be merged in `master`, we need to follow the regular 
process
+and create a Pull Request on github.
+
+## 7. Write release notes
+
+Check the milestone in Github associated with the release.
+https://github.com/apache/pulsar/milestones?closed=1
+
+In the release item, add the list of most important changes that happened in 
the
+release and a link to the associated milestone, with the complete list of all 
the
+changes.
+
+## 8. Run the vote
+
+Send an email on the Pulsar Dev mailing list:
+
+```
+To: [email protected]
+Subject: [VOTE] Pulsar Release 2.X.0 Candidate 1
+
+This is the first release candidate for Apache Pulsar, version 2.X.0.
+
+It fixes the following issues:
+https://github.com/apache/pulsar/milestone/8?closed=1
+
+*** Please download, test and vote on this release. This vote will stay open
+for at least 72 hours ***
+
+Note that we are voting upon the source (tag), binaries are provided for
+convenience.
+
+Source and binary files:
+https://dist.apache.org/repos/dist/dev/pulsar/pulsar-2.X.0-candidate-1/
+
+SHA-512 checksums:
+
+028313cbbb24c5647e85a6df58a48d3c560aacc9  
apache-pulsar-2.X.0-SNAPSHOT-bin.tar.gz
+f7cc55137281d5257e3c8127e1bc7016408834b1  
apache-pulsar-2.x.0-SNAPSHOT-src.tar.gz
+
+Maven staging repo:
+https://repository.apache.org/content/repositories/orgapachepulsar-169/
+
+The tag to be voted upon:
+v2.X.0-candidate-1 (21f4a4cffefaa9391b79d79a7849da9c539af834)
+https://github.com/apache/pulsar/releases/tag/v2.X.0-candidate-1
+
+Pulsar's KEYS file containing PGP keys we use to sign the release:
+https://dist.apache.org/repos/dist/dev/pulsar/KEYS
+
+Please download the source package, and follow the README to build
+and run the Pulsar standalone service.
+```
+
+The vote should be open for at least 72 hours (3 days). Votes from Pulsar PMC 
members
+will be considered binding, while anyone else is encouraged to verify the 
release and
+vote as well.
+
+If the release is approved here, we can then proceed to next step.
+
+## 9. Promote the release
+
+Create the final git tag:
+
+```shell
+git tag -u [email protected] v2.X.0 -m 'Release v2.X.0'
+git push origin v2.X.0
+```
+
+Promote the artifacts on the release location(repo 
https://dist.apache.org/repos/dist/release limited to PMC, You may need a PMC 
member's help if you are not one):
+```shell
+svn move -m "Release Apache Pulsar 2.X.Y" 
https://dist.apache.org/repos/dist/dev/pulsar/pulsar-2.X.0-candidate-1 \
+         https://dist.apache.org/repos/dist/release/pulsar/pulsar-2.X.0
+```
+
+Promote the Maven staging repository for release. Login to 
`https://repository.apache.org` and
+select the staging repository associated with the RC candidate that was 
approved. The naming
+will be like `orgapachepulsar-XYZ`. Select the repository and click on 
"Release". Artifacts
+will now be made available on Maven central.
+
+## 10. Publish Docker Images
+
+Choose either A. or B. depending if you have access to apachepulsar org in 
hub.docker.com. There's a limited number of users that are allowed in the 
account.
+
+### A. No push access to apachepulsar org - use Personal account for staging 
the Docker images
+
+#### Publish Docker Images to personal account in hub.docker.com (if you don't 
have access to apachepulsar org)
+
+- a) Run `cd $PULSAR_HOME/docker && ./build.sh` build docker images.
+- b) Run `cd $PULSAR_HOME/docker && DOCKER_PASSWORD="hub.docker.com token 
here" DOCKER_ORG=dockerhubuser DOCKER_USER=dockerhubuser ./publish.sh` to 
publish all images
+- c) Try to run `docker pull ${DOCKER_ORG}/pulsar:<tag>` to fetch the image, 
run the docker in standalone mode and make sure the docker image is okay.
+
+
+#### Copy Docker image from the Release manager's personal account to 
apachepulsar org
+
+Ask a person with access to apachepulsar org in hub.docker.com to copy the 
docker images from your (release manager) personal acccount to apachepulsar org.
+```
+PULSAR_VERSION=2.x.x
+OTHER_DOCKER_USER=otheruser
+for image in pulsar pulsar-all pulsar-grafana pulsar-standalone; do
+    docker pull "${OTHER_DOCKER_USER}/$image:${PULSAR_VERSION}" && {
+      docker tag "${OTHER_DOCKER_USER}/$image:${PULSAR_VERSION}" 
"apachepulsar/$image:${PULSAR_VERSION}"
+      echo "Pushing apachepulsar/$image:${PULSAR_VERSION}"
+      docker push "apachepulsar/$image:${PULSAR_VERSION}"
+    }
+done
+```
+
+### B. Push access to apachepulsar org
+
+This is alternative to A. when the user has access to apachepulsar org in 
hub.docker.com.
+
+#### Publish Docker Images directly to apachepulsar org in hub.docker.com
+
+- a) Run `cd $PULSAR_HOME/docker && ./build.sh` build docker images.
+- b) Run `cd $PULSAR_HOME/docker && DOCKER_PASSWORD="hub.docker.com token 
here" DOCKER_USER=dockerhubuser ./publish.sh` to publish all images
+- c) Try to run `docker pull pulsar:<tag>` to fetch the image, run the docker 
in standalone mode and make sure the docker image is okay.
+
+
+## 11. Release Helm Chart
+
+1. Bump the image version in the Helm Chart: 
[charts/pulsar/values.yaml](https://github.com/apache/pulsar-helm-chart/blob/master/charts/pulsar/values.yaml)
+
+2. Bump the chart version and `appVersion` in the Helm Chart to the released 
version: 
[charts/pulsar/Chart.yaml](https://github.com/apache/pulsar-helm-chart/blob/master/charts/pulsar/Chart.yaml)
+
+3. Send a pull request for reviews and get it merged.
+
+4. Once it is merged, the chart will be automatically released to Github 
releases at https://github.com/apache/pulsar-helm-chart and updated to 
https://pulsar.apache.org/charts.
+
+## 12. Publish Python Clients
+
+> **NOTES**
+>
+> 1. You need to create an account on PyPI: 
https://pypi.org/project/pulsar-client/
+>
+> 2. Ask Matteo or Sijie for adding you as a maintainer for pulsar-docker on 
PyPI
+
+### Linux
+
+There is a script that builds and packages the Python client inside Docker 
images.
+
+> Make sure you run following command at the release tag!!
+
+```shell
+$ pulsar-client-cpp/docker/build-wheels.sh
+```
+
+The wheel files will be left under `pulsar-client-cpp/python/wheelhouse`. Make 
sure all the files has `manylinux` in the filenames. Otherwise those files will 
not be able to upload to PyPI.
+
+Run following command to push the built wheel files.
+
+```shell
+$ cd pulsar-client-cpp/python/wheelhouse
+$ pip install twine
+$ twine upload pulsar_client-*.whl
+```
+
+### MacOS
+
+> **NOTES**
+>
+> You need to install following softwares before proceeding:
+>
+> - [VirtualBox](https://www.virtualbox.org/)
+> - [VirtualBox Extension Pack]
+> - [Vagrant](https://www.vagrantup.com/)
+> - [Vagrant-scp](https://github.com/invernizzi/vagrant-scp)
+>
+> And make sure your laptop have enough disk spaces (> 30GB) since the build 
scripts
+> will download MacOS images, launch them in VirtualBox and build the python
+> scripts.
+
+Build the python scripts.
+
+```shell
+$ cd pulsar-client-cpp/python/pkg/osx/
+$ ./generate-all-wheel.sh v2.X.Y
+```
+
+The wheel files will be generated at each platform directory under 
`pulsar-client-cpp/python/pkg/osx/`.
+Then you can run `twin upload` to upload those wheel files.
+
+If you don't have enough spaces, you can build the python wheel file platform 
by platform and remove the images under `~/.vagrant.d/boxes` between each run.
+
+## 13. Publish MacOS libpulsar package
+Release a new version of libpulsar for MacOS, You can follow the example 
[here](https://github.com/Homebrew/homebrew-core/pull/53514)
+
+## 14. Update Python Client docs
+
+After publishing the python client docs, run the following script:
+
+```shell
+PULSAR_VERSION=2.X.Y ./site2/tools/api/python/build-docs-in-docker.sh
+```
+
+Note that it builds the docs within a docker image, so you'll need to have 
docker running.
+
+Once the docs are generated, you can add them and submit them in a PR. The 
expected doc output is `site2/website/static/api/python`.
+
+## 15. Update swagger file
+
+> For major release, the swagger file update happen under `master` branch.
+> while for minor release, swagger file is created from branch-2.x, and need 
copy to a new branch based on master.
+
+```shell
+git checkout branch-2.X
+mvn -am -pl pulsar-broker install -DskipTests -Pswagger
+git checkout master
+git checkout -b fix/swagger-file
+mkdir -p site2/website/static/swagger/2.X.0
+cp pulsar-broker/target/docs/*.json site2/website/static/swagger/2.X.0
+```
+Send out a PR request for review.
+
+## 16. Write release notes
+
+Steps and examples see [Pulsar Release Notes 
Guide](https://docs.google.com/document/d/1cwNkBefKyV6OPbEXnUrcCdVZi0i2BezqL6vAL7VqVC0/edit#).
+
+## 17. Update the site
+
+The workflow for updating the site is slightly different for major and minor 
releases.
+
+### Update the site for major releases
+For major release, the website is updated based on the `master` branch.
+
+1. Create a new branch off master
+
+```shell
+git checkout -b doc_release_<release-version>
+```
+
+2. Go to the website directory
+
+```shell
+cd site2/website
+```
+
+3. Generate a new version of the documentation.
+
+```shell
+yarn install
+yarn run version <release-version>
+```
+
+After you run this command, a new folder `version-<release-version>` is added 
in the `site2/website/versioned_docs` directory, a new sidebar file 
`version-<release-version>-sidebars.json` is added in the 
`site2/website/versioned_sidebars` directory, and the new version is added in 
the `versions.json` file, shown as follows:
+
+  ```shell
+  versioned_docs/version-<release-version>
+  versioned_sidebars/version-<release-version>-sidebars.json 
+  ```
+
+> Note: You can move the latest version under the old version in the 
`versions.json` file. Make sure the Algolia index works before moving 2.X.0 as 
the current stable.
+
+4. Update `releases.json` file by adding `<release-version>` to the second of 
the list(this is to make search could work. After your PR is merged, the Pulsar 
website is built and tagged for search, you can change it to the first list).
+
+5. Send out a PR request for review.
+
+   After your PR is approved and merged to master, the website is published 
automatically after new website build. The website is built every 6 hours.
+
+6. Check the new website after website build.  
+   Open https://pulsar.apache.org in your browsers to verify all the changes 
are alive. If the website build succeeds but the website is not updated, you 
can try to Sync git repository. Navigate to https://selfserve.apache.org/ and 
click the "Synchronize Git Repositories" and then select apache/pulsar.
+
+7. Publish the release on GitHub, and copy the same release notes: 
https://github.com/apache/pulsar/releases
+
+8. Update the deploy version to the current release version in 
deployment/terraform-ansible/deploy-pulsar.yaml
+
+9. Generate the doc set and sidebar file for the next minor release `2.X.1` 
based on the `site2/docs` folder. You can follow step 1, 2, 3 and submit those 
files to apache/pulsar repository. This step is a preparation for `2.X.1` 
release.
+
+### Update the site for minor releases
+
+The new updates for the minor release docs are processed in its doc set and 
sidebar file directly before release. You can follow step 4~8 (in major 
release) to update the site. You'll also need to add this new version to 
`versions.json`.
+
+To make preparation for the next minor release, you need to generate the doc 
set and sidebar file based on the previous release. Take `2.X.2` as example, 
`2.X.2` doc set and sidebar.json file are generated based on `2.X.1`. You can 
make it with the following steps:
+
+1. Copy the `version-2.X.1` doc set and `version-2.X.1-sidebars.json` file and 
rename them as `version-2.X.2` doc set and `version-2.X.2-sidebars.json` file.
+
+2. Update the "id" from `version-2.X.1` to `version-2.X.2` for the md files in 
the `version-2.X.2` doc set and `version-2.X.2-sidebars.json` file.
+
+3. Submit the new doc set and sidebar.json file to the apache/pulsar 
repository.
+
+> **Note**
+> - The `yarn run version <release-version>` command generates the new doc set 
and sidebar.json file based on the `site2/docs` folder.
+> - The minor release doc is generated based on the previous minor release 
(e.g.: `2.X.2` doc is generated based on `2.X.1`, and `2.X.3`doc is generated 
based on `2.X.2`), so you cannot use the `yarn run version <release-version>` 
command directly.
+
+## 18. Announce the release
+
+Once the release artifacts are available in the Apache Mirrors and the website 
is updated,
+we need to announce the release.
+
+Send an email on these lines:
+
+```
+To: [email protected], [email protected], [email protected]
+Subject: [ANNOUNCE] Apache Pulsar 2.X.0 released
+
+The Apache Pulsar team is proud to announce Apache Pulsar version 2.X.0.
+
+Pulsar is a highly scalable, low latency messaging platform running on
+commodity hardware. It provides simple pub-sub semantics over topics,
+guaranteed at-least-once delivery of messages, automatic cursor management for
+subscribers, and cross-datacenter replication.
+
+For Pulsar release details and downloads, visit:
+
+https://pulsar.apache.org/download
+
+Release Notes are at:
+https://pulsar.apache.org/release-notes
+
+We would like to thank the contributors that made the release possible.
+
+Regards,
+
+The Pulsar Team
+```
+
+Send the email in plain text mode since the [email protected] mailing list 
will reject messages with text/html content.
+In Gmail, there's an option to set `Plain text mode` in the `⋮`/ `More 
options` menu.
+
+
+## 19. Write a blog post for the release (optional)
+
+It is encouraged to write a blog post to summarize the features introduced in 
this release,
+especially for feature releases.
+You can follow the example [here](https://github.com/apache/pulsar/pull/2308)
+
+## 20. Remove old releases
+
+Remove the old releases (if any). We only need the latest release there, older 
releases are
+available through the Apache archive:
+
+```shell
+# Get the list of releases
+svn ls https://dist.apache.org/repos/dist/release/pulsar
+
+# Delete each release (except for the last one)
+svn rm https://dist.apache.org/repos/dist/release/pulsar/pulsar-2.Y.0
+```
+
+## 21. Move branch to next version
+
+Follow the instructions in step 6, but run the script on the release branch.
+
+```shell
+./src/set-project-version.sh 2.X.Y-SNAPSHOT
+```
\ No newline at end of file

Reply via email to