You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by li...@apache.org on 2022/12/19 14:07:24 UTC

[arrow-adbc] branch main updated: chore: set up release process (#174)

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

lidavidm pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-adbc.git


The following commit(s) were added to refs/heads/main by this push:
     new 9f3c283  chore: set up release process (#174)
9f3c283 is described below

commit 9f3c283126d91887b074847001aed0ec48083d4e
Author: David Li <li...@gmail.com>
AuthorDate: Mon Dec 19 09:07:18 2022 -0500

    chore: set up release process (#174)
    
    Co-authored-by: Sutou Kouhei <ko...@cozmixng.org>
---
 .github/workflows/packaging-wheels.yml             |   2 +-
 .gitignore                                         |  11 +-
 ci/conda_env_cpp.txt                               |   1 +
 ci/conda_env_dev.txt                               |   3 +
 ci/scripts/cpp_test.sh                             |   8 +-
 ci/conda_env_cpp.txt => dev/release/.env.example   |  18 +-
 dev/release/01-prepare.sh                          |  67 +++++
 dev/release/02-source.sh                           | 108 ++++++++
 dev/release/03-binary-sign.sh                      | 160 ++++++++++++
 dev/release/04-java-upload.sh                      |  10 +-
 dev/release/05-binary-verify.sh                    |  56 ++++
 dev/release/check-rat-report.py                    |  60 +++++
 dev/release/post-01-upload.sh                      |  47 ++++
 .../{04-java-upload.sh => post-02-binary.sh}       |  48 ++--
 dev/release/post-03-python.sh                      |  71 ++++++
 ci/conda_env_cpp.txt => dev/release/post-04-go.sh  |  25 +-
 dev/release/post-05-remove-old-artifacts.sh        |  58 +++++
 .../release/post-06-bump-versions.sh               |  38 ++-
 dev/release/rat_exclude_files.txt                  |   4 +
 ci/conda_env_cpp.txt => dev/release/run-rat.sh     |  34 ++-
 .../release/setup-gpg-agent.sh                     |  15 +-
 dev/release/utils-prepare.sh                       |  62 +++++
 dev/release/verify-release-candidate.sh            |   4 +-
 docs/source/{ => development}/contributing.rst     |   0
 docs/source/{ => development}/nightly.rst          |   0
 docs/source/development/releasing.rst              | 284 +++++++++++++++++++++
 docs/source/index.rst                              |   7 +-
 .../adbc_driver_manager/_version.py                |   4 +-
 .../adbc_driver_postgresql/_version.py             |   4 +-
 .../adbc_driver_sqlite/_version.py                 |   4 +-
 30 files changed, 1126 insertions(+), 87 deletions(-)

diff --git a/.github/workflows/packaging-wheels.yml b/.github/workflows/packaging-wheels.yml
index f24fe90..4df8682 100644
--- a/.github/workflows/packaging-wheels.yml
+++ b/.github/workflows/packaging-wheels.yml
@@ -23,7 +23,7 @@ on:
     branches-ignore:
       - '**'
     tags:
-      - 'adbc-*-rc*'
+      - 'apache-arrow-adbc-*-rc*'
   schedule:
     - cron: "0 0 * * *"
   workflow_dispatch:
diff --git a/.gitignore b/.gitignore
index 7c71f9c..d09ff82 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,9 +15,16 @@
 # specific language governing permissions and limitations
 # under the License.
 
+# Release artifacts
+apache-arrow-adbc-*.tar.gz
+apache-arrow-adbc-*.tar.gz.asc
+apache-arrow-adbc-*.tar.gz.sha256
+apache-arrow-adbc-*.tar.gz.sha512
 apache-rat-*.jar
-arrow-src.tar
-arrow-src.tar.gz
+dev/release/.env
+filtered_rat.txt
+packages/
+rat.txt
 
 # Compiled source
 *.a
diff --git a/ci/conda_env_cpp.txt b/ci/conda_env_cpp.txt
index b312e8d..fe42d44 100644
--- a/ci/conda_env_cpp.txt
+++ b/ci/conda_env_cpp.txt
@@ -21,5 +21,6 @@ gmock>=1.10.0
 gtest>=1.10.0
 libpq
 ninja
+pkg-config
 libsqlite
 pkg-config
diff --git a/ci/conda_env_dev.txt b/ci/conda_env_dev.txt
index 99ad394..48e6707 100644
--- a/ci/conda_env_dev.txt
+++ b/ci/conda_env_dev.txt
@@ -15,4 +15,7 @@
 # specific language governing permissions and limitations
 # under the License.
 
+commitizen
+gh
 pre-commit
+twine
diff --git a/ci/scripts/cpp_test.sh b/ci/scripts/cpp_test.sh
index d99a2c1..9bd989f 100755
--- a/ci/scripts/cpp_test.sh
+++ b/ci/scripts/cpp_test.sh
@@ -31,12 +31,8 @@ test_subproject() {
 
     pushd "${build_dir}/${subproject}"
 
-    if [[ "${subproject}" = "driver_manager" ]]; then
-        # macOS will not propagate DYLD_LIBRARY_PATH through a subprocess
-        ./adbc-driver-manager-test
-    else
-        ctest --output-on-failure --no-tests=error
-    fi
+    # macOS will not propagate DYLD_LIBRARY_PATH through a subprocess
+    "./adbc-$(echo ${subproject} | sed "s|[/_]|-|g")-test"
 
     popd
 }
diff --git a/ci/conda_env_cpp.txt b/dev/release/.env.example
similarity index 68%
copy from ci/conda_env_cpp.txt
copy to dev/release/.env.example
index b312e8d..cc7fd58 100644
--- a/ci/conda_env_cpp.txt
+++ b/dev/release/.env.example
@@ -15,11 +15,13 @@
 # specific language governing permissions and limitations
 # under the License.
 
-cmake
-compilers
-gmock>=1.10.0
-gtest>=1.10.0
-libpq
-ninja
-libsqlite
-pkg-config
+# The GPG key ID to sign artifacts. The GPG key ID must be registered
+# to both of the followings:
+#
+#   * https://dist.apache.org/repos/dist/dev/arrow/KEYS
+#   * https://dist.apache.org/repos/dist/release/arrow/KEYS
+#
+# See these files how to import your GPG key ID to these files.
+#
+# You must set this.
+#GPG_KEY_ID=08D3564B7C6A9CAFBFF6A66791D18FCF079F8007
diff --git a/dev/release/01-prepare.sh b/dev/release/01-prepare.sh
new file mode 100755
index 0000000..62e1ce0
--- /dev/null
+++ b/dev/release/01-prepare.sh
@@ -0,0 +1,67 @@
+#!/usr/bin/env bash
+#
+# 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.
+#
+set -ue
+
+SOURCE_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+
+if [ "$#" -ne 3 ]; then
+  echo "Usage: $0 <version> <next_version> <rc-num>"
+  exit 1
+fi
+
+. $SOURCE_DIR/utils-prepare.sh
+
+version=$1
+next_version=$2
+next_version_snapshot="${next_version}-SNAPSHOT"
+rc_number=$3
+
+release_candidate_tag="apache-arrow-adbc-${version}-rc${rc_number}"
+
+if [[ $(git tag -l "${release_candidate_tag}") ]]; then
+    next_rc_number=$(($rc_number+1))
+    echo "Tag ${release_candidate_tag} already exists, so create a new release candidate:"
+    echo "1. Create or checkout maint-<version>."
+    echo "2. Execute the script again with bumped RC number."
+    echo "Commands:"
+    echo "   git checkout maint-${version}"
+    echo "   dev/release/01-prepare.sh ${version} ${next_version} ${next_rc_number}"
+    exit 1
+fi
+
+############################## Pre-Tag Commits ##############################
+
+echo "Updating changelog for $version"
+# Update changelog
+cz ch --incremental --unreleased-version "ADBC Libraries ${version} RC ${rc_number}"
+git add ${SOURCE_DIR}/../../CHANGELOG.md
+git commit -m "chore: update CHANGELOG.md for $version"
+
+echo "Prepare release ${version} on tag ${release_candidate_tag}"
+
+update_versions "${version}" "${next_version}" "release"
+git commit -m "chore: update versions for ${version}"
+
+######################### Tag the Release Candidate #########################
+
+git tag -a "${release_candidate_tag}" -m "ADBC Libraries ${version} RC ${rc_number}"
+
+echo "Created release candidate tag: ${release_candidate_tag}"
+echo "Push this tag before continuing!"
diff --git a/dev/release/02-source.sh b/dev/release/02-source.sh
new file mode 100755
index 0000000..34f8681
--- /dev/null
+++ b/dev/release/02-source.sh
@@ -0,0 +1,108 @@
+#!/usr/bin/env bash
+# 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.
+
+set -eu
+
+: ${SOURCE_UPLOAD:="0"}
+
+main() {
+    local -r source_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+    local -r source_top_dir="$( cd "${source_dir}/../../" && pwd )"
+
+    if type shasum >/dev/null 2>&1; then
+        local -r sha256_generate="shasum -a 256"
+        local -r sha512_generate="shasum -a 512"
+    else
+        local -r sha256_generate="sha256sum"
+        local -r sha512_generate="sha512sum"
+    fi
+
+    if [ "$#" -ne 2 ]; then
+        echo "Usage: $0 <version> <rc-num>"
+        exit 1
+    fi
+    local -r version="$1"
+    local -r rc_number="$2"
+    local -r tag="apache-arrow-adbc-${version}-rc${rc_number}"
+
+    echo "Preparing source for tag ${tag}"
+    local -r release_hash=$(cd "${source_top_dir}" && git rev-list --max-count=1 ${tag} --)
+
+    if [[ -z "${release_hash}" ]]; then
+        echo "Cannot continue: unknown Git tag: ${tag}"
+        exit 1
+    fi
+
+    echo "Using commit ${release_hash}"
+
+    local -r tarball="${tag}.tar.gz"
+
+    pushd "${source_top_dir}"
+
+    rm -rf "${tag}/"
+    git archive "${release_hash}" --prefix "${tag}/" | tar xf -
+
+    # Resolve all hard and symbolic links
+    rm -rf "${tag}.tmp/"
+    mv "${tag}/" "${tag}.tmp/"
+    cp -R -L "${tag}.tmp" "${tag}"
+    rm -rf "${tag}.tmp/"
+
+    # Create new tarball
+    tar czf "${tarball}" "${tag}/"
+    rm -rf "${tag}/"
+
+    # check licenses
+    "${source_dir}/run-rat.sh" "${tarball}"
+
+    # Sign the archive
+    gpg --armor --output "${tarball}.asc" --detach-sig "${tarball}"
+    ${sha256_generate} "${tarball}" | tee "${tarball}.sha256"
+    ${sha512_generate} "${tarball}" | tee "${tarball}.sha512"
+
+    # Upload
+    if [[ "${SOURCE_UPLOAD}" -gt 0 ]]; then
+        echo "Uploading to dist.apache.org"
+
+        local -r tagrc="${tag}"
+
+        # check out the arrow RC folder
+        svn co --depth=empty https://dist.apache.org/repos/dist/dev/arrow tmp
+
+        # add the release candidate for the tag
+        mkdir -p "tmp/${tagrc}"
+
+        # copy the rc tarball into the tmp dir
+        cp ${tarball}* "tmp/${tagrc}"
+
+        # commit to svn
+        svn add "tmp/${tagrc}"
+        svn ci -m "Apache Arrow ADBC ${version} RC${rc}" "tmp/${tagrc}"
+
+        # clean up
+        rm -rf tmp
+
+        echo "Uploaded at https://dist.apache.org/repos/dist/dev/arrow/${tagrc}"
+    fi
+
+    echo "Commit SHA1: ${release_hash}"
+
+    popd
+}
+
+main "$@"
diff --git a/dev/release/03-binary-sign.sh b/dev/release/03-binary-sign.sh
new file mode 100755
index 0000000..5d5f283
--- /dev/null
+++ b/dev/release/03-binary-sign.sh
@@ -0,0 +1,160 @@
+#!/usr/bin/env bash
+# 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.
+
+set -eu
+
+main() {
+    local -r source_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+    local -r source_top_dir="$( cd "${source_dir}/../../" && pwd )"
+    pushd "${source_top_dir}"
+
+    if [ "$#" -ne 2 ]; then
+        echo "Usage: $0 <version> <rc-num>"
+        exit 1
+    fi
+
+    local -r version="$1"
+    local -r rc_number="$2"
+    local -r tag="apache-arrow-adbc-${version}-rc${rc_number}"
+
+    : ${REPOSITORY:="apache/arrow-adbc"}
+
+    if [[ ! -f "${source_dir}/.env" ]]; then
+        echo "You must create ${source_dir}/.env"
+        echo "You can use ${source_dir}/.env.example as a template"
+    fi
+
+    source "${source_dir}/.env"
+
+    header "Looking for GitHub Actions workflow on ${REPOSITORY}:${tag}"
+    local run_id=""
+    while [[ -z "${run_id}" ]]
+    do
+        echo "Waiting for run to start..."
+        run_id=$(gh run list \
+                    --repo "${REPOSITORY}" \
+                    --workflow=packaging-wheels.yml \
+                    --json 'databaseId,event,headBranch,status' \
+                    --jq ".[] | select(.event == \"push\" and .headBranch == \"${tag}\") | .databaseId")
+        sleep 1
+    done
+
+    header "Found GitHub Actions workflow with ID: ${run_id}"
+    gh run watch --repo "${REPOSITORY}" --exit-status ${run_id}
+    gh run view --repo "${REPOSITORY}" "${run_id}"
+
+    header "Downloading assets from release"
+    local -r download_dir="packages/${tag}"
+    mkdir -p "${download_dir}"
+    gh release download \
+       "${tag}" \
+       --repo "${REPOSITORY}" \
+       --dir "${download_dir}" \
+       --skip-existing
+
+    header "Adding release notes"
+    local -r release_notes=$(cz ch --dry-run "${tag}" --unreleased-version "ADBC Libraries ${version}")
+    echo "${release_notes}"
+    gh release edit \
+       "${tag}" \
+       --repo "${REPOSITORY}" \
+       --notes "${release_notes}"
+
+    header "Upload signed tarballs"
+    gh release upload \
+       --repo "${REPOSITORY}" \
+       "${tag}" \
+       "${tag}.tar.gz" \
+       "${tag}.tar.gz.asc" \
+       "${tag}.tar.gz.sha256" \
+       "${tag}.tar.gz.sha512"
+
+    header "Upload signatures for Java"
+    upload_asset_signatures "${tag}" $(find "${download_dir}" -type f \( -name '*.jar' -or -name '*.pom' \))
+
+    header "Upload signatures for Python"
+    upload_asset_signatures "${tag}" $(find "${download_dir}" -type f \( -name '*.whl' -or -name 'adbc_*.tar.gz' \))
+
+    header "Upload signatures for docs"
+    upload_asset_signatures "${tag}" "${download_dir}/docs.tgz"
+
+    popd
+}
+
+header() {
+    echo "============================================================"
+    echo "${1}"
+    echo "============================================================"
+}
+
+sign_asset() {
+    local -r asset="$1"
+    local -r sigfile="${asset}.asc"
+
+    if [[ -f "${sigfile}" ]]; then
+        if env LANG=C gpg --verify "${sigfile}" "${asset}" >/dev/null 2>&1; then
+            echo "Valid signature at $(basename "${sigfile}"), skipping"
+            return
+        fi
+        rm "${sigfile}"
+    fi
+
+    gpg \
+        --armor \
+        --detach-sign \
+        --local-user "${GPG_KEY_ID}" \
+        --output "${sigfile}" \
+        "${asset}"
+    echo "Generated $(basename "${sigfile}")"
+}
+
+sum_asset() {
+    local -r asset="$1"
+    local -r sumfile="${asset}.sha512"
+
+    local -r digest=$(cd $(dirname "${asset}"); shasum --algorithm 512 $(basename "${asset}"))
+    if [[ -f "${sumfile}" ]]; then
+        if [[ "${digest}" = $(cat "${sumfile}") ]]; then
+            echo "Valid digest at $(basename "${sumfile}"), skipping"
+            return
+        fi
+    fi
+
+    echo "${digest}" > "${sumfile}"
+    echo "Generated $(basename "${sumfile}")"
+}
+
+upload_asset_signatures() {
+    local -r tag="${1}"
+    shift 1
+
+    local -r assets=("$@")
+
+    for asset in "${assets[@]}"; do
+        sign_asset "${asset}"
+        sum_asset "${asset}"
+    done
+
+    gh release upload \
+       --repo "${REPOSITORY}" \
+       "${tag}" \
+       "${assets[@]/%/.asc}" \
+       "${assets[@]/%/.sha512}"
+}
+
+main "$@"
diff --git a/dev/release/04-java-upload.sh b/dev/release/04-java-upload.sh
index fae7817..f7606bb 100755
--- a/dev/release/04-java-upload.sh
+++ b/dev/release/04-java-upload.sh
@@ -32,11 +32,11 @@ main() {
     fi
 
     local -r arrow_dir="$(cd "$1" && pwd)"
-    local -r version="$1"
-    local -r rc_number="$2"
-    local -r tag="adbc-${version}-rc${rc_number}"
+    local -r version="$2"
+    local -r rc_number="$3"
+    local -r tag="apache-arrow-adbc-${version}-rc${rc_number}"
 
-    : ${ADBC_REPOSITORY:="apache/arrow-adbc"}
+    : ${REPOSITORY:="apache/arrow-adbc"}
 
     export ARROW_ARTIFACTS_DIR="$(pwd)/packages/${tag}/java"
     rm -rf "${ARROW_ARTIFACTS_DIR}"
@@ -47,7 +47,7 @@ main() {
        --pattern "*.jar.asc" \
        --pattern "*.pom" \
        --pattern "*.pom.asc" \
-       --repo "${ADBC_REPOSITORY}" \
+       --repo "${REPOSITORY}" \
        "${tag}"
 
     export UPLOAD_FORCE_SIGN=0
diff --git a/dev/release/05-binary-verify.sh b/dev/release/05-binary-verify.sh
new file mode 100755
index 0000000..d4a17d8
--- /dev/null
+++ b/dev/release/05-binary-verify.sh
@@ -0,0 +1,56 @@
+#!/usr/bin/env bash
+# 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.
+
+set -euo pipefail
+
+main() {
+    local -r source_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+    local -r source_top_dir="$( cd "${source_dir}/../../" && pwd )"
+
+    local -r version="$1"
+    local -r rc_number="$2"
+    local -r tag="apache-arrow-adbc-${version}-rc${rc_number}"
+
+    : ${REPOSITORY:="apache/arrow-adbc"}
+
+    echo "Starting GitHub Actions workflow on ${REPOSITORY} for ${version} RC${rc_number}"
+
+    gh workflow run \
+       --repo "${REPOSITORY}" \
+       --ref "${tag}" \
+       verify.yml \
+       --raw-field version="${version}" \
+       --raw-field rc="${rc_number}"
+
+    local run_id=""
+    while [[ -z "${run_id}" ]]
+    do
+        echo "Waiting for run to start..."
+        run_id=$(gh run list \
+                    --repo "${REPOSITORY}" \
+                    --workflow=verify.yml \
+                    --json 'databaseId,event,headBranch,status' \
+                    --jq ".[] | select(.event == \"workflow_dispatch\" and .headBranch == \"${tag}\" and .status != \"completed\") | .databaseId")
+        sleep 1
+    done
+
+    echo "Started GitHub Actions workflow with ID: ${run_id}"
+    echo "You can wait for completion via: gh run watch --repo ${REPOSITORY} ${run_id}"
+}
+
+main "$@"
diff --git a/dev/release/check-rat-report.py b/dev/release/check-rat-report.py
new file mode 100644
index 0000000..718189a
--- /dev/null
+++ b/dev/release/check-rat-report.py
@@ -0,0 +1,60 @@
+#!/usr/bin/env python
+##############################################################################
+# 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.
+##############################################################################
+import fnmatch
+import re
+import sys
+import xml.etree.ElementTree as ET
+
+if len(sys.argv) != 3:
+    sys.stderr.write("Usage: %s exclude_globs.lst rat_report.xml\n" % sys.argv[0])
+    sys.exit(1)
+
+exclude_globs_filename = sys.argv[1]
+xml_filename = sys.argv[2]
+
+globs = [line.strip() for line in open(exclude_globs_filename, "r")]
+
+tree = ET.parse(xml_filename)
+root = tree.getroot()
+resources = root.findall("resource")
+
+all_ok = True
+for r in resources:
+    approvals = r.findall("license-approval")
+    if not approvals or approvals[0].attrib["name"] == "true":
+        continue
+    clean_name = re.sub("^[^/]+/", "", r.attrib["name"])
+    excluded = False
+    for g in globs:
+        if fnmatch.fnmatch(clean_name, g):
+            excluded = True
+            break
+    if not excluded:
+        sys.stdout.write(
+            "NOT APPROVED: %s (%s): %s\n"
+            % (clean_name, r.attrib["name"], approvals[0].attrib["name"])
+        )
+        all_ok = False
+
+if not all_ok:
+    sys.exit(1)
+
+print("OK")
+sys.exit(0)
diff --git a/dev/release/post-01-upload.sh b/dev/release/post-01-upload.sh
new file mode 100755
index 0000000..e857278
--- /dev/null
+++ b/dev/release/post-01-upload.sh
@@ -0,0 +1,47 @@
+#!/usr/bin/env bash
+# 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.
+
+set -eu
+
+main() {
+    if [ "$#" -ne 2 ]; then
+        echo "Usage: $0 <version> <rc-num>"
+        exit 1
+    fi
+    local -r version="$1"
+    local -r rc_number="$2"
+    local -r tag="apache-arrow-adbc-${version}-rc${rc_number}"
+
+    rc_id="apache-arrow-adbc-${version}-rc${rc_number}"
+    release_id="apache-arrow-adbc-${version}"
+    echo "Copying dev/ to release/"
+    svn \
+        cp \
+        -m "Apache Arrow ADBC ${version}" \
+        https://dist.apache.org/repos/dist/dev/arrow/${rc_id} \
+        https://dist.apache.org/repos/dist/release/arrow/${release_id}
+
+    echo "Create final tag"
+    git tag -a "apache-arrow-adbc-${version}" -m "ADBC Libraries ${version}" "${tag}^{}"
+
+    echo "Success! The release is available here:"
+    echo "  https://dist.apache.org/repos/dist/release/arrow/${release_id}"
+    echo "Please push the tag apache-arrow-adbc-${version}!"
+}
+
+main "$@"
diff --git a/dev/release/04-java-upload.sh b/dev/release/post-02-binary.sh
similarity index 50%
copy from dev/release/04-java-upload.sh
copy to dev/release/post-02-binary.sh
index fae7817..7774645 100755
--- a/dev/release/04-java-upload.sh
+++ b/dev/release/post-02-binary.sh
@@ -22,36 +22,34 @@ set -u
 set -o pipefail
 
 main() {
-    local -r source_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
-    local -r source_top_dir="$(cd "${source_dir}/../../" && pwd)"
+    local -r source_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+    local -r source_top_dir="$( cd "${source_dir}/../../" && pwd )"
 
-    if [ $# -ne 3 ]; then
-        echo "Usage: $0 <arrow-dir> <version> <rc-number>"
-        echo "Usage: $0 ../arrow 1.0.0 0"
-        exit
+    if [ "$#" -ne 2 ]; then
+        echo "Usage: $0 <version> <rc-num>"
+        exit 1
     fi
 
-    local -r arrow_dir="$(cd "$1" && pwd)"
     local -r version="$1"
     local -r rc_number="$2"
-    local -r tag="adbc-${version}-rc${rc_number}"
-
-    : ${ADBC_REPOSITORY:="apache/arrow-adbc"}
-
-    export ARROW_ARTIFACTS_DIR="$(pwd)/packages/${tag}/java"
-    rm -rf "${ARROW_ARTIFACTS_DIR}"
-    mkdir -p "${ARROW_ARTIFACTS_DIR}"
-    gh release download \
-       --dir "${ARROW_ARTIFACTS_DIR}" \
-       --pattern "*.jar" \
-       --pattern "*.jar.asc" \
-       --pattern "*.pom" \
-       --pattern "*.pom.asc" \
-       --repo "${ADBC_REPOSITORY}" \
-       "${tag}"
-
-    export UPLOAD_FORCE_SIGN=0
-    "${arrow_dir}/dev/release/06-java-upload.sh" "${version}" "${rc_number}"
+    local -r tag="apache-arrow-adbc-${version}-rc${rc_number}"
+
+    : ${REPOSITORY:="apache/arrow-adbc"}
+
+    header "Publishing release ${version}"
+
+    gh release edit \
+       --repo "${REPOSITORY}" \
+       "${tag}" \
+       --title="ADBC Libraries ${version}" \
+       --prerelease=false \
+       --tag="apache-arrow-adbc-${version}"
+}
+
+header() {
+    echo "============================================================"
+    echo "${1}"
+    echo "============================================================"
 }
 
 main "$@"
diff --git a/dev/release/post-03-python.sh b/dev/release/post-03-python.sh
new file mode 100755
index 0000000..40e5559
--- /dev/null
+++ b/dev/release/post-03-python.sh
@@ -0,0 +1,71 @@
+#!/usr/bin/env bash
+#
+# 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.
+
+set -e
+set -u
+set -o pipefail
+
+main() {
+    local -r source_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+    local -r source_top_dir="$( cd "${source_dir}/../../" && pwd )"
+
+    if [ "$#" -ne 2 ]; then
+        echo "Usage: $0 <version> <rc-num>"
+        exit 1
+    fi
+
+    local -r version="$1"
+    local -r rc_number="$2"
+    local -r tag="apache-arrow-adbc-${version}"
+
+    : ${REPOSITORY:="apache/arrow-adbc"}
+
+    local -r tmp=$(mktemp -d -t "arrow-post-python.XXXXX")
+
+    header "Downloading Python packages for ${version}"
+
+    gh release download \
+       --repo "${REPOSITORY}" \
+       "${tag}" \
+       --dir "${tmp}" \
+       --pattern "*.whl" \
+       --pattern "adbc_*.tar.gz" # sdist
+
+    header "Uploading Python packages for ${version}"
+
+    TWINE_ARGS=""
+    if [ "${TEST_PYPI:-0}" -gt 0 ]; then
+        echo "Using test.pypi.org"
+        TWINE_ARGS="${TWINE_ARGS} --repository-url https://test.pypi.org/legacy/"
+    fi
+
+    twine upload ${TWINE_ARGS} ${tmp}/*
+
+    rm -rf "${tmp}"
+
+    echo "Success!"
+}
+
+header() {
+    echo "============================================================"
+    echo "${1}"
+    echo "============================================================"
+}
+
+main "$@"
diff --git a/ci/conda_env_cpp.txt b/dev/release/post-04-go.sh
old mode 100644
new mode 100755
similarity index 70%
copy from ci/conda_env_cpp.txt
copy to dev/release/post-04-go.sh
index b312e8d..9023bb8
--- a/ci/conda_env_cpp.txt
+++ b/dev/release/post-04-go.sh
@@ -1,3 +1,5 @@
+#!/usr/bin/env bash
+#
 # 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
@@ -14,12 +16,19 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
+#
+set -ue
+
+SOURCE_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+
+if [ "$#" -ne 1 ]; then
+    echo "Usage: $0 <version>"
+    exit
+fi
+
+version=$1
+version_tag="apache-arrow-adbc-${version}"
+go_arrow_tag="go/v${version}"
 
-cmake
-compilers
-gmock>=1.10.0
-gtest>=1.10.0
-libpq
-ninja
-libsqlite
-pkg-config
+git tag "${go_arrow_tag}" "${version_tag}"
+git push apache "${go_arrow_tag}"
diff --git a/dev/release/post-05-remove-old-artifacts.sh b/dev/release/post-05-remove-old-artifacts.sh
new file mode 100755
index 0000000..7a59f0b
--- /dev/null
+++ b/dev/release/post-05-remove-old-artifacts.sh
@@ -0,0 +1,58 @@
+#!/usr/bin/env bash
+#
+# 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.
+
+set -e
+set -u
+set -o pipefail
+
+echo "Remove all RCs"
+dev_base_url=https://dist.apache.org/repos/dist/dev/arrow
+old_rcs=$(
+  svn ls ${dev_base_url}/ | \
+  grep -E '^apache-arrow-adbc-[0-9]' | \
+  sort --version-sort
+)
+for old_rc in $old_rcs; do
+  echo "Remove RC: ${old_rc}"
+  svn \
+    delete \
+    -m "Remove old Apache Arrow ADBC RC: ${old_rc}" \
+    ${dev_base_url}/${old_rc}
+done
+
+echo "Keep only the latest release"
+release_base_url=https://dist.apache.org/repos/dist/release/arrow
+old_releases=$(
+  svn ls ${release_base_url}/ | \
+  grep -E '^apache-arrow-adbc-[0-9]' | \
+  sort --version-sort --reverse | \
+  tail -n +2 | \
+  tac
+)
+for old_release_version in $old_releases; do
+  echo "Remove old release: ${old_release_version}"
+  svn \
+    delete \
+    -m "Remove old Apache Arrow ADBC release: ${old_release_version}" \
+    ${release_base_url}/${old_release_version}
+done
+
+echo "Success! See the current artifacts:"
+echo "  ${dev_base_url}/"
+echo "  ${release_base_url}/"
diff --git a/ci/conda_env_cpp.txt b/dev/release/post-06-bump-versions.sh
old mode 100644
new mode 100755
similarity index 51%
copy from ci/conda_env_cpp.txt
copy to dev/release/post-06-bump-versions.sh
index b312e8d..850e3bc
--- a/ci/conda_env_cpp.txt
+++ b/dev/release/post-06-bump-versions.sh
@@ -1,3 +1,5 @@
+#!/usr/bin/env bash
+#
 # 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
@@ -14,12 +16,32 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
+#
+set -ue
+
+SOURCE_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+
+if [ "$#" -ne 2 ]; then
+  echo "Usage: $0 <version> <next_version>"
+  exit 1
+fi
+
+. $SOURCE_DIR/utils-prepare.sh
+
+version=$1
+next_version=$2
+next_version_snapshot="${next_version}-SNAPSHOT"
+
+########################## Update Snapshot Version ##########################
+
+git fetch --all --prune --tags --force -j$(nproc)
+git switch main
+git rebase apache/main
+
+echo "Updating versions for ${next_version_snapshot}"
+update_versions "${version}" "${next_version}" "snapshot"
+git commit -m "chore: update versions for ${next_version_snapshot}"
+echo "Bumped versions on branch."
 
-cmake
-compilers
-gmock>=1.10.0
-gtest>=1.10.0
-libpq
-ninja
-libsqlite
-pkg-config
+echo "Pushing changes to apache/arrow-adbc:main"
+git push apache main
diff --git a/dev/release/rat_exclude_files.txt b/dev/release/rat_exclude_files.txt
new file mode 100644
index 0000000..1024579
--- /dev/null
+++ b/dev/release/rat_exclude_files.txt
@@ -0,0 +1,4 @@
+*.json
+dev/release/rat_exclude_files.txt
+go/adbc/status_string.go
+go/adbc/go.sum
diff --git a/ci/conda_env_cpp.txt b/dev/release/run-rat.sh
old mode 100644
new mode 100755
similarity index 51%
copy from ci/conda_env_cpp.txt
copy to dev/release/run-rat.sh
index b312e8d..2596a28
--- a/ci/conda_env_cpp.txt
+++ b/dev/release/run-rat.sh
@@ -1,3 +1,5 @@
+#!/usr/bin/env bash
+#
 # 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
@@ -14,12 +16,28 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
+#
+
+RAT_VERSION=0.13
+
+# download apache rat
+if [ ! -f apache-rat-${RAT_VERSION}.jar ]; then
+  curl -s https://repo1.maven.org/maven2/org/apache/rat/apache-rat/${RAT_VERSION}/apache-rat-${RAT_VERSION}.jar > apache-rat-${RAT_VERSION}.jar
+fi
+
+RAT="java -jar apache-rat-${RAT_VERSION}.jar -x "
+
+RELEASE_DIR=$(cd "$(dirname "$BASH_SOURCE")"; pwd)
+
+# generate the rat report
+$RAT $1 > rat.txt
+python $RELEASE_DIR/check-rat-report.py $RELEASE_DIR/rat_exclude_files.txt rat.txt > filtered_rat.txt
+cat filtered_rat.txt
+UNAPPROVED=`cat filtered_rat.txt  | grep "NOT APPROVED" | wc -l`
 
-cmake
-compilers
-gmock>=1.10.0
-gtest>=1.10.0
-libpq
-ninja
-libsqlite
-pkg-config
+if [ "0" -eq "${UNAPPROVED}" ]; then
+  echo "No unapproved licenses"
+else
+  echo "${UNAPPROVED} unapproved licences. Check rat report: rat.txt"
+  exit 1
+fi
diff --git a/ci/conda_env_cpp.txt b/dev/release/setup-gpg-agent.sh
similarity index 84%
copy from ci/conda_env_cpp.txt
copy to dev/release/setup-gpg-agent.sh
index b312e8d..9ff84f6 100644
--- a/ci/conda_env_cpp.txt
+++ b/dev/release/setup-gpg-agent.sh
@@ -1,3 +1,5 @@
+#!/usr/bin/env bash
+#
 # 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
@@ -14,12 +16,9 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
+#
 
-cmake
-compilers
-gmock>=1.10.0
-gtest>=1.10.0
-libpq
-ninja
-libsqlite
-pkg-config
+# source me
+eval $(gpg-agent --daemon --allow-preset-passphrase)
+gpg --use-agent -s LICENSE.txt
+rm -rf LICENSE.txt.gpg
diff --git a/dev/release/utils-prepare.sh b/dev/release/utils-prepare.sh
new file mode 100644
index 0000000..1c56088
--- /dev/null
+++ b/dev/release/utils-prepare.sh
@@ -0,0 +1,62 @@
+# 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.
+
+ADBC_DIR="${SOURCE_DIR}/../.."
+
+update_versions() {
+  local base_version=$1
+  local next_version=$2
+  local type=$3
+
+  case ${type} in
+    release)
+      local version=${base_version}
+      local docs_version=${base_version}
+      ;;
+    snapshot)
+      local version=${next_version}-SNAPSHOT
+      local docs_version="${next_version} (dev)"
+      ;;
+  esac
+  local major_version=${version%%.*}
+
+  pushd "${ADBC_DIR}/c/"
+  sed -i.bak -E "s/set\(ADBC_VERSION \".+\"\)/set(ADBC_VERSION \"${version}\")/g" cmake_modules/AdbcVersion.cmake
+  rm cmake_modules/AdbcVersion.cmake.bak
+  git add cmake_modules/AdbcVersion.cmake
+  popd
+
+  sed -i.bak -E "s/release = \".+\"/release = \"${docs_version}\"/g" "${ADBC_DIR}/docs/source/conf.py"
+  rm "${ADBC_DIR}/docs/source/conf.py.bak"
+  git add "${ADBC_DIR}/docs/source/conf.py"
+
+  pushd "${ADBC_DIR}/java/"
+  mvn versions:set "-DnewVersion=${version}"
+  find . -type f -name pom.xml.versionsBackup -delete
+  sed -i.bak -E "s|<adbc.version>.+</adbc.version>|<adbc.version>${version}</adbc.version>|g" pom.xml
+  rm pom.xml.bak
+  git add "pom.xml" "**/pom.xml"
+  popd
+
+  sed -i.bak -E "s/version: '.+'/release = '${version}'/g" "${ADBC_DIR}/glib/meson.build"
+  rm "${ADBC_DIR}/glib/meson.build.bak"
+  git add "${ADBC_DIR}/glib/meson.build"
+
+  sed -i.bak -E "s/VERSION = \".+\"/VERSION = \"${version}\"/g" "${ADBC_DIR}/ruby/lib/adbc/version.rb"
+  rm "${ADBC_DIR}/ruby/lib/adbc/version.rb.bak"
+  git add "${ADBC_DIR}/ruby/lib/adbc/version.rb"
+}
diff --git a/dev/release/verify-release-candidate.sh b/dev/release/verify-release-candidate.sh
index 8f9276b..96e858e 100755
--- a/dev/release/verify-release-candidate.sh
+++ b/dev/release/verify-release-candidate.sh
@@ -488,7 +488,7 @@ test_go() {
 ensure_source_directory() {
   show_header "Ensuring source directory"
 
-  dist_name="adbc-${VERSION}"
+  dist_name="apache-arrow-adbc-${VERSION}"
 
   if [ "${SOURCE_KIND}" = "local" ]; then
     # Local arrow repository, testing repositories should be already present
@@ -570,7 +570,7 @@ test_binary_distribution() {
                        --dest="${BINARY_DIR}" \
                        --package_type=github \
                        --repository="${SOURCE_REPOSITORY}" \
-                       --tag="adbc-${VERSION}-rc${RC_NUMBER}"
+                       --tag="apache-arrow-adbc-${VERSION}-rc${RC_NUMBER}"
   fi
 
   if [ ${TEST_BINARY} -gt 0 ]; then
diff --git a/docs/source/contributing.rst b/docs/source/development/contributing.rst
similarity index 100%
rename from docs/source/contributing.rst
rename to docs/source/development/contributing.rst
diff --git a/docs/source/nightly.rst b/docs/source/development/nightly.rst
similarity index 100%
rename from docs/source/nightly.rst
rename to docs/source/development/nightly.rst
diff --git a/docs/source/development/releasing.rst b/docs/source/development/releasing.rst
new file mode 100644
index 0000000..58ee2a1
--- /dev/null
+++ b/docs/source/development/releasing.rst
@@ -0,0 +1,284 @@
+.. 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 Management Guide
+========================
+
+This page provides detailed information on the steps followed to perform
+a release. It can be used both as a guide to learn the ADBC release
+process and as a comprehensive checklist for the Release Manager when
+performing a release.
+
+.. seealso::
+
+   `Apache Arrow Release Management Guide
+   <https://arrow.apache.org/docs/dev/developers/release.html>`_
+
+Principles
+==========
+
+The Apache Arrow Release follows the guidelines defined at the
+`Apache Software Foundation Release Policy <https://www.apache.org/legal/release-policy.html>`_.
+
+Preparing for the release
+=========================
+
+Some steps of the release require being a committer or a PMC member.
+
+- A GPG key in the Apache Web of Trust to sign artifacts. This will have to be cross signed by other Apache committers/PMC members. You must set your GPG key ID in ``dev/release/.env`` (see ``dev/release/.env.example`` for a template).
+
+- The GPG key needs to be added to this `SVN repo <https://dist.apache.org/repos/dist/dev/arrow/>`_ and `this one <https://dist.apache.org/repos/dist/release/arrow/>`_.
+- Configure Maven to `publish artifacts to Apache repositories <http://www.apache.org/dev/publishing-maven-artifacts.html>`_. You will need to `setup a master password <https://maven.apache.org/guides/mini/guide-encryption.html>`_ at ``~/.m2/settings-security.xml`` and ``settings.xml`` as specified on the `Apache guide <http://www.apache.org/dev/publishing-maven-artifacts.html#dev-env>`_. It can be tested with the following command:
+
+  .. code-block::
+
+      # You might need to export GPG_TTY=$(tty) to properly prompt for a passphrase
+      mvn clean install -Papache-release
+
+- Install ``en_US.UTF-8`` locale. You can confirm available locales by ``locale -a``.
+- Install Conda with conda-forge, and create and activate the environment.
+
+  .. code-block::
+
+     mamba create -n adbc -c conda-forge --file ci/conda_env_dev.txt
+
+  This will install two tools used in the release process: ``commitizen`` (generates changelog from commit messages) and ``gh`` (submit jobs/download artifacts).
+
+Before creating a Release Candidate
+===================================
+
+.. code-block::
+
+   # Setup gpg agent for signing artifacts
+   source dev/release/setup-gpg-agent.sh
+
+   # Activate conda environment
+   mamba activate adbc
+
+Creating a Release Candidate
+============================
+
+These are the different steps that are required to create a Release Candidate.
+
+For the initial Release Candidate, we will create a maintenance branch from master.
+Follow up Release Candidates will update the maintenance branch by cherry-picking
+specific commits.
+
+We have implemented a Feature Freeze policy between Release Candidates.
+This means that, in general, we should only add bug fixes between Release Candidates.
+In rare cases, critical features can be added between Release Candidates, if
+there is community consensus.
+
+Create or update the corresponding maintenance branch
+-----------------------------------------------------
+
+.. tab-set::
+
+   .. tab-item:: Initial Release Candidate
+
+      .. code-block::
+
+         # Execute the following from an up to date master branch.
+         # This will create a branch locally called maint-X.Y.Z.
+         # X.Y.Z corresponds with the Major, Minor and Patch version number
+         # of the release respectively. As an example 9.0.0
+         git branch maint-X.Y.Z
+         # Push the maintenance branch to the remote repository
+         git push -u apache maint-X.Y.Z
+
+   .. tab-item:: Follow up Release Candidates
+
+      .. code-block::
+
+         # First cherry-pick any commits by hand.
+         git switch maint-X.Y.Z
+         git cherry-pick ...
+         # Push the updated maintenance branch to the remote repository
+         git push -u apache maint-X.Y.Z
+
+Create the Release Candidate branch from the updated maintenance branch
+-----------------------------------------------------------------------
+
+.. code-block::
+
+   # Start from the updated maintenance branch.
+   git switch maint-X.Y.Z
+
+   # The following script will create a branch for the Release Candidate,
+   # place the necessary commits updating the version number and changelog, and then create a git tag
+   # on OSX use gnu-sed with homebrew: brew install gnu-sed (and export to $PATH)
+   #
+   # <rc-number> starts at 0 and increments every time the Release Candidate is burned
+   # so for the first RC this would be: dev/release/01-prepare.sh 4.0.0 5.0.0 0
+
+   dev/release/01-prepare.sh <version> <next-version> <rc-number>
+
+   git push -u apache apache-arrow-adbc-<version>-rc<rc-number>
+
+Build source and binaries and submit them
+-----------------------------------------
+
+.. code-block::
+
+    # Build the source release tarball
+    dev/release/02-source.sh <version> <rc-number>
+
+    # Download the produced binaries, sign them, and add the
+    # signatures to the GitHub release
+    #
+    # On macOS the only way I could get this to work was running "echo
+    # "UPDATESTARTUPTTY" | gpg-connect-agent" before running this
+    # comment otherwise I got errors referencing "ioctl" errors.
+    dev/release/03-binary-sign.sh <version> <rc-number>
+
+    # Sign and upload the Java artifacts
+    #
+    # Note that you need to press the "Close" button manually by Web interface
+    # after you complete the script:
+    #   https://repository.apache.org/#stagingRepositories
+    dev/release/04-java-upload.sh <version> <rc-number>
+
+    # Start verifications for binaries and wheels
+    dev/release/05-binary-verify.sh <version> <rc-number>
+
+Verify the Release
+------------------
+
+Start the vote thread on dev@arrow.apache.org.
+
+Voting and approval
+===================
+
+Start the vote thread on dev@arrow.apache.org and supply instructions for verifying the integrity of the release.
+Approval requires a net of 3 +1 votes from PMC members. A release cannot be vetoed.
+
+Post-release tasks
+==================
+
+After the release vote, we must undertake many tasks to update source artifacts, binary builds, and the Arrow website.
+
+Be sure to go through on the following checklist:
+
+.. dropdown:: Close the GitHub milestone/project
+   :class-title: sd-fs-5
+   :class-container: sd-shadow-md
+
+   - Open https://github.com/orgs/apache/projects and find the project
+   - Click "..." for the project
+   - Select "Close"
+   - Open https://github.com/apache/arrow-adbc/milestones and find the milestone
+   - Click "Close"
+
+.. dropdown:: Add the new release to the Apache Reporter System
+   :class-title: sd-fs-5
+   :class-container: sd-shadow-md
+
+   Add relevant release data for Arrow to `Apache reporter <https://reporter.apache.org/addrelease.html?arrow>`_.
+
+.. dropdown:: Upload source release artifacts to Subversion
+   :class-title: sd-fs-5
+   :class-container: sd-shadow-md
+
+   A PMC member must commit the source release artifacts to Subversion:
+
+   .. code-block:: Bash
+
+      # dev/release/post-01-upload.sh 0.1.0 0
+      dev/release/post-01-upload.sh <version> <rc>
+      git push --tag apache apache-arrow-adbc-<version>
+
+.. dropdown:: Create the final GitHub release
+   :class-title: sd-fs-5
+   :class-container: sd-shadow-md
+
+   A committer must create the final GitHub release:
+
+   .. code-block:: Bash
+
+      # dev/release/post-02-binary.sh 0.1.0 0
+      dev/release/post-02-binary.sh <version> <rc number>
+
+.. dropdown:: Update website
+   :class-title: sd-fs-5
+   :class-container: sd-shadow-md
+
+   This is done automatically when the tags are pushed. Please check that the
+   `nightly-website.yml`_ workflow succeeded.
+
+.. dropdown:: Upload wheels/sdist to PyPI
+   :class-title: sd-fs-5
+   :class-container: sd-shadow-md
+
+   We use the twine tool to upload wheels to PyPI:
+
+   .. code-block:: Bash
+
+      # dev/release/post-03-python.sh 10.0.0
+      dev/release/post-03-python.sh <version>
+
+.. dropdown:: Publish Maven packages
+   :class-title: sd-fs-5
+   :class-container: sd-shadow-md
+
+   - Logon to the Apache repository: https://repository.apache.org/#stagingRepositories
+   - Select the Arrow staging repository you created for RC: ``orgapachearrow-XXXX``
+   - Click the ``release`` button
+
+.. dropdown:: Update tags for Go modules
+   :class-title: sd-fs-5
+   :class-container: sd-shadow-md
+
+   .. code-block:: Bash
+
+      # dev/release/post-04-go.sh 10.0.0
+      dev/release/post-04-go.sh X.Y.Z
+
+.. dropdown:: Announce the new release
+   :class-title: sd-fs-5
+   :class-container: sd-shadow-md
+
+   Write a release announcement (see `example <https://lists.apache.org/thread/6rkjwvyjjfodrxffllh66pcqnp729n3k>`_) and send to announce@apache.org and dev@arrow.apache.org.
+
+   The announcement to announce@apache.org must be sent from your apache.org e-mail address to be accepted.
+
+.. dropdown:: Publish release blog post
+   :class-title: sd-fs-5
+   :class-container: sd-shadow-md
+
+   TODO
+
+.. dropdown:: Remove old artifacts
+   :class-title: sd-fs-5
+   :class-container: sd-shadow-md
+
+   Remove RC artifacts on https://dist.apache.org/repos/dist/dev/arrow/ and old release artifacts on https://dist.apache.org/repos/dist/release/arrow to follow `the ASF policy <https://infra.apache.org/release-download-pages.html#current-and-older-releases>`_:
+
+   .. code-block:: Bash
+
+      dev/release/post-05-remove-old-artifacts.sh
+
+.. dropdown:: Bump versions
+   :class-title: sd-fs-5
+   :class-container: sd-shadow-md
+
+   .. code-block:: Bash
+
+      # dev/release/post-06-bump-versions.sh 0.1.0 0.2.0
+      dev/release/post-06-bump-versions.sh <version> <next_version>
+
+.. _nightly-website.yml: https://github.com/apache/arrow-adbc/actions/workflows/nightly-website.yml
diff --git a/docs/source/index.rst b/docs/source/index.rst
index f913ae0..a0c558a 100644
--- a/docs/source/index.rst
+++ b/docs/source/index.rst
@@ -65,10 +65,11 @@ Arrow-native database protocols.
 
 .. toctree::
    :maxdepth: 1
-   :caption: Contributing
+   :caption: Development:
 
-   contributing
-   nightly
+   development/contributing
+   development/nightly
+   development/releasing
 
 Indices and tables
 ==================
diff --git a/python/adbc_driver_manager/adbc_driver_manager/_version.py b/python/adbc_driver_manager/adbc_driver_manager/_version.py
index 363720a..8eadf0e 100644
--- a/python/adbc_driver_manager/adbc_driver_manager/_version.py
+++ b/python/adbc_driver_manager/adbc_driver_manager/_version.py
@@ -34,7 +34,9 @@ package_root = os.path.dirname(os.path.realpath(__file__))
 package_name = os.path.basename(package_root)
 
 STATIC_VERSION_FILE = "_static_version.py"
-TAG_RELEASE_FORMAT = re.compile(r"^adbc-([0-9]+\.[0-9]+\.[0-9]+)(?:-rc[0-9]+)?$")
+TAG_RELEASE_FORMAT = re.compile(
+    r"^apache-arrow-adbc-([0-9]+\.[0-9]+\.[0-9]+)(?:-rc[0-9]+)?$"
+)
 
 
 def get_version(version_file=STATIC_VERSION_FILE):
diff --git a/python/adbc_driver_postgresql/adbc_driver_postgresql/_version.py b/python/adbc_driver_postgresql/adbc_driver_postgresql/_version.py
index 363720a..8eadf0e 100644
--- a/python/adbc_driver_postgresql/adbc_driver_postgresql/_version.py
+++ b/python/adbc_driver_postgresql/adbc_driver_postgresql/_version.py
@@ -34,7 +34,9 @@ package_root = os.path.dirname(os.path.realpath(__file__))
 package_name = os.path.basename(package_root)
 
 STATIC_VERSION_FILE = "_static_version.py"
-TAG_RELEASE_FORMAT = re.compile(r"^adbc-([0-9]+\.[0-9]+\.[0-9]+)(?:-rc[0-9]+)?$")
+TAG_RELEASE_FORMAT = re.compile(
+    r"^apache-arrow-adbc-([0-9]+\.[0-9]+\.[0-9]+)(?:-rc[0-9]+)?$"
+)
 
 
 def get_version(version_file=STATIC_VERSION_FILE):
diff --git a/python/adbc_driver_sqlite/adbc_driver_sqlite/_version.py b/python/adbc_driver_sqlite/adbc_driver_sqlite/_version.py
index 363720a..8eadf0e 100644
--- a/python/adbc_driver_sqlite/adbc_driver_sqlite/_version.py
+++ b/python/adbc_driver_sqlite/adbc_driver_sqlite/_version.py
@@ -34,7 +34,9 @@ package_root = os.path.dirname(os.path.realpath(__file__))
 package_name = os.path.basename(package_root)
 
 STATIC_VERSION_FILE = "_static_version.py"
-TAG_RELEASE_FORMAT = re.compile(r"^adbc-([0-9]+\.[0-9]+\.[0-9]+)(?:-rc[0-9]+)?$")
+TAG_RELEASE_FORMAT = re.compile(
+    r"^apache-arrow-adbc-([0-9]+\.[0-9]+\.[0-9]+)(?:-rc[0-9]+)?$"
+)
 
 
 def get_version(version_file=STATIC_VERSION_FILE):