This is an automated email from the ASF dual-hosted git repository.
kou pushed a commit to branch main
in repository
https://gitbox.apache.org/repos/asf/arrow-flight-sql-postgresql.git
The following commit(s) were added to refs/heads/main by this push:
new c626804 Add release script (#87)
c626804 is described below
commit c6268049a3c4d707893eebe114a37a3324bffc58
Author: Sutou Kouhei <[email protected]>
AuthorDate: Thu Aug 31 16:14:31 2023 +0900
Add release script (#87)
Closes GH-30
---
.github/workflows/doc.yaml | 4 +-
.github/workflows/package.yaml | 23 +--
.gitignore | 1 +
Rakefile | 333 ++++++++++++++++++++++++++++++++-
.gitignore => dev/release/.env.example | 32 ++--
src/afs.cc | 29 ++-
6 files changed, 382 insertions(+), 40 deletions(-)
diff --git a/.github/workflows/doc.yaml b/.github/workflows/doc.yaml
index a7f960c..63982af 100644
--- a/.github/workflows/doc.yaml
+++ b/.github/workflows/doc.yaml
@@ -64,9 +64,9 @@ jobs:
run: |
mkdir -p site.repository
pushd site.repository
- git init --initial-branch=asf-site
+ git init --initial-branch=asf-site --bare
popd
- git clone file://${PWD}/site.repository/.git site
+ git clone file://${PWD}/site.repository/ site
- name: Publish
run: |
git config --global user.name 'github-actions[bot]'
diff --git a/.github/workflows/package.yaml b/.github/workflows/package.yaml
index 027fbd7..8ead9ce 100644
--- a/.github/workflows/package.yaml
+++ b/.github/workflows/package.yaml
@@ -40,9 +40,9 @@ jobs:
- uses: actions/checkout@v3
- name: Make RC GA
run: |
- rc_tag=$(gh release list ${GITHUB_REF_NAME} | \
+ rc_tag=$(gh release list | \
cut -d' ' -f3 | \
- grep -rc | \
+ grep -F "${GITHUB_REF_NAME}-rc" | \
head -n1)
title="$(gh release view ${rc_tag} --json name --jq .name | \
sed -E -e 's/ RC[0-9]+$//')"
@@ -52,6 +52,7 @@ jobs:
gh release create ${GITHUB_REF_NAME} \
--notes-file release-note.md \
--title "${title}" \
+ --verify-tag \
rc_artifacts/*
env:
GH_TOKEN: ${{ github.token }}
@@ -84,8 +85,8 @@ jobs:
puts(ARGF.read.split(/^## /)[1]. \
gsub(/ {.+?}/, ""). \
gsub(/\[(.+?)\]\[.+?\]/) {$1})' \
- docs/source/news.md > release-note.md
- rc=${GITHUB_REF_NAME:#*-rc}
+ doc/source/release-notes.md > release-note.md
+ rc=${GITHUB_REF_NAME#*-rc}
title="$(head -n1 release-note.md | sed -e 's/^## //') RC${rc}"
tail -n +2 release-note.md > release-note-without-version.md
gh release create ${GITHUB_REF_NAME} \
@@ -109,8 +110,8 @@ jobs:
fail-fast: false
matrix:
target:
- - "postgresql-15-pgdg-debian-bookworm-amd64"
- - "postgresql-15-pgdg-ubuntu-jammy-amd64"
+ - "debian-bookworm-amd64-postgresql-15-pgdg"
+ - "ubuntu-jammy-amd64-postgresql-15-pgdg"
steps:
- uses: actions/checkout@v3
with:
@@ -125,13 +126,13 @@ jobs:
echo "BASE_NAME=${BASE_NAME}" >> $GITHUB_ENV
echo "ARROW_SOURCE=$(pwd)/arrow" >> $GITHUB_ENV
full_target=${{ matrix.target }}
- # postgresql-15-pgdg-debian-bookworm-amd64 ->
+ # debian-bookworm-amd64-postgresql-15-pgdg ->
# postgresql-15-pgdg
- PACKAGE=${full_target%-pgdg-*}-pgdg
+ PACKAGE=postgresql-${full_target#*-postgresql-}
echo "PACKAGE=${PACKAGE}" >> $GITHUB_ENV
- # postgresql-15-pgdg-debian-bookworm-amd64 ->
+ # debian-bookworm-amd64-postgresql-15-pgdg ->
# debian-bookworm-amd64
- PACKAGE_TARGET=${full_target#*-pgdg-}
+ PACKAGE_TARGET=${full_target%-postgresql-*}
echo "APT_TARGETS=${PACKAGE_TARGET}" >> $GITHUB_ENV
echo "YUM_TARGETS=${PACKAGE_TARGET}" >> $GITHUB_ENV
case ${PACKAGE_TARGET} in
@@ -194,7 +195,7 @@ jobs:
if: |
github.ref_type == 'tag'
run: |
- gh release upload ${GITHUB_REF_NAME} \
+ gh release upload --repo ${GITHUB_REPOSITORY} ${GITHUB_REF_NAME} \
${{ matrix.target }}.tar.gz
env:
GH_TOKEN: ${{ github.token }}
diff --git a/.gitignore b/.gitignore
index b75d024..9eff26e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,6 +19,7 @@
/.cache/
/Gemfile.lock
/compile_commands.json
+/dev/release/.env
/dev/release/apache-rat-0.13.jar
/dev/release/dist
/dev/release/filtered_rat.txt
diff --git a/Rakefile b/Rakefile
index 9dfa179..657eaae 100644
--- a/Rakefile
+++ b/Rakefile
@@ -17,10 +17,14 @@
# specific language governing permissions and limitations
# under the License.
+require "digest/sha2"
+require "json"
require "tmpdir"
require_relative "helper"
+project_label = "Apache Arrow Flight SQL adapter for PostgreSQL"
+
version = Helper.detect_version
archive_base_name = "apache-arrow-flight-sql-postgresql-#{version}"
archive_name = "#{archive_base_name}.tar.gz"
@@ -65,11 +69,15 @@ namespace :doc do
Dir.mktmpdir do |tmp|
is_release = (ENV["GITHUB_REF_TYPE"] == "tag")
if is_release
- new_version = ENV["GITHUB_REF_NAME"].gsub(/-rc\d+\z/, "")
+ tag = ENV["GITHUB_REF_NAME"]
+ new_version = tag.gsub(/-rc\d+\z/, "")
+ is_release_candiate = (tag != new_version)
new_doc = "#{tmp}/new"
build_doc(new_doc, for_publish: true)
- current_doc = "#{tmp}/current"
- build_doc(current_doc, release: "current", for_publish: true)
+ unless is_release_candiate
+ current_doc = "#{tmp}/current"
+ build_doc(current_doc, release: "current", for_publish: true)
+ end
else
devel_doc = "#{tmp}/devel"
build_doc(devel_doc, release: "devel", for_publish: true)
@@ -86,7 +94,7 @@ namespace :doc do
add.call(index_html, "index.html")
if is_release
add.call(new_doc, new_version)
- add.call(current_doc, "current")
+ add.call(current_doc, "current") unless is_release_candiate
else
add.call(devel_doc, "devel")
end
@@ -100,3 +108,320 @@ namespace :doc do
end
end
end
+
+def load_env
+ env_file = "dev/release/.env"
+ unless File.exist?(env_file)
+ raise "must create #{env_file} from #{env_file}.example"
+ end
+ File.readlines(env_file, chomp: true).each do |line|
+ line.strip!
+ next if line.empty?
+ next if line.start_with?("#")
+ name, value = line.split("=", 2)
+ next if value.nil?
+ name.strip!
+ value.strip!
+ ENV[name] ||= value
+ end
+end
+
+def env_value(name, default=nil)
+ value = ENV[name]
+ if value.nil? and default.nil?
+ raise "must set environment variable: #{name}"
+ end
+ value || default
+end
+
+def github_repository
+ env_value("GITHUB_REPOSITORY", "apache/arrow-flight-sql-postgresql")
+end
+
+def gpg_key_id
+ env_value("GPG_KEY_ID")
+end
+
+def arrow_source
+ env_value("ARROW_SOURCE")
+end
+
+def detect_latest_rc(version)
+ rc_tags = `git tag`.each_line(chomp: true).select do |tag|
+ tag.start_with?("#{version}-rc")
+ end
+ rcs = rc_tags.collect do |rc_tag|
+ Integer(rc_tag.delete_prefix("#{version}-rc"), 10)
+ end
+ rcs.max
+end
+
+def package_directories
+ Dir.glob("package/postgresql-*")
+end
+
+def debian_changelog_latest_version(changelog_path)
+ (File.readlines(changelog_path)[0] || "")[/\(([\d.]+)-\d+\)/, 1]
+end
+
+def validate_rc(version)
+ package_directories.each do |dir|
+ latest_version = debian_changelog_latest_version("#{dir}/debian/changelog")
+ if latest_version != version
+ raise "'rake release:rc:prepare && git push' is needed"
+ end
+ end
+
+ release_notes = File.read("doc/source/release-notes.md").split(/^## /)
+ latest_release_note = release_notes[1]
+ latest_release_note_version = latest_release_note.lines[0].strip
+ if latest_release_note_version != version
+ raise "add a release note to doc/source/release-notes.md"
+ end
+end
+
+def ensure_package_job_finished(rc_tag)
+ run_id = nil
+ while run_id.nil?
+ runs = IO.pipe do |read, write|
+ sh("gh", "run", "list",
+ "--json", "databaseId,headBranch",
+ "--repo", github_repository,
+ "--workflow", "package.yaml",
+ out: write)
+ write.close
+ read.read
+ end
+ run = JSON.parse(runs).find {|rc| rc["headBranch"] == rc_tag}
+ run_id = run&.fetch("databaseId")
+ end
+ sh("gh", "run", "watch",
+ "--repo", github_repository,
+ "--exit-status",
+ run_id.to_s)
+end
+
+namespace :release do
+ namespace :rc do
+ desc "Prepare a new RC"
+ task :prepare do
+ prepared = false
+ package_directories.each do |dir|
+ cd(dir) do
+ debian_changelog = "debian/changelog"
+ latest_version = debian_changelog_latest_version(debian_changelog)
+ next if latest_version == version
+ ruby("-S", "rake", "version:update")
+ sh("git", "add", debian_changelog)
+ prepared = true
+ end
+ end
+ sh("git", "commit", "-m", "Prepare #{version} RC #{new_rc}")
+ end
+
+ desc "Tag a new RC"
+ task :tag do
+ validate_rc(version)
+ new_rc = (detect_latest_rc(version) || 0) + 1
+ rc_tag = "#{version}-rc#{new_rc}"
+ sh("git", "tag",
+ "-a", rc_tag,
+ "-m", "#{project_label} #{version} RC #{new_rc}")
+ if env_value("TAG_PUSH", "no") == "yes"
+ sh("git", "push", "upstream", rc_tag)
+ else
+ puts("Push #{rc_tag}:")
+ puts(" git push upstream #{rc_tag}")
+ end
+ end
+
+ desc "Sign the latest RC"
+ task :sign do
+ load_env
+ rc = detect_latest_rc(version)
+ if rc.nil?
+ raise "'rake release:rc:tag && git push ...' is needed"
+ end
+ rc_tag = "#{version}-rc#{rc}"
+ ensure_package_job_finished(rc_tag)
+ Dir.mktmpdir do |tmp|
+ sh("gh", "release", "download",
+ "--dir", tmp,
+ "--pattern", archive_name,
+ "--repo", github_repository,
+ rc_tag)
+ tmp_archive_name = "#{tmp}/#{archive_name}"
+ tmp_sign_name = "#{tmp_archive_name}.asc"
+ sh("gpg",
+ "--armor",
+ "--detach-sign",
+ "--local-user", gpg_key_id,
+ "--output", tmp_sign_name,
+ "#{tmp_archive_name}")
+ tmp_checksum_name = "#{tmp_archive_name}.sha512"
+ File.open(tmp_checksum_name, "w") do |output|
+ checksum = Digest::SHA512.file(tmp_archive_name)
+ output.puts("#{checksum} #{archive_name}")
+ end
+ sh("gh", "release", "upload",
+ "--clobber",
+ "--repo", github_repository,
+ rc_tag,
+ tmp_sign_name,
+ tmp_checksum_name)
+ end
+ end
+
+ desc "Upload Linux packages"
+ task :linux do
+ load_env
+ rc = detect_latest_rc(version)
+ if rc.nil?
+ raise "'rake release:rc:tag && git push ...' is needed"
+ end
+ rc_tag = "#{version}-rc#{rc}"
+ Dir.mktmpdir do |tmp|
+ sh("gh", "release", "download",
+ "--dir", tmp,
+ "--pattern", "debian-*.tar.gz",
+ "--pattern", "ubuntu-*.tar.gz",
+ "--repo", github_repository,
+ rc_tag)
+ Dir.glob("#{tmp}/*.tar.gz") do |tar_gz|
+ sh("tar", "xf", tar_gz,
+ "--directory", tmp,
+ "--one-top-level")
+ end
+ env = {
+ "ARROW_ARTIFACTS_DIR" => tmp,
+ "DEB_PACKAGE_NAME" => "apache-arrow-flight-sql-postgresql",
+ "UPLOAD_DEFAULT" => "0",
+ "UPLOAD_DEBIAN" => "1",
+ "UPLOAD_UBUNTU" => "1",
+ }
+ sh(env,
+ "#{arrow_source}/dev/release/05-binary-upload.sh",
+ version,
+ rc.to_s)
+ end
+ end
+
+ desc "Generate a release vote e-mail"
+ task :vote do
+ load_env
+ rc = detect_latest_rc(version)
+ if rc.nil?
+ raise "'rake release:rc:tag && git push ...' is needed"
+ end
+ rc_tag = "#{version}-rc#{rc}"
+ commit = IO.pipe do |read, write|
+ sh("git", "rev-list", "-n", "1", rc_tag, write: write)
+ write.close
+ read.read.strip
+ end
+ puts(<<-MAIL)
+ local -r commit=$(git rev-list -n 1 "${tag}")
+
+ cat <<MAIL
+To: [email protected]
+Subject: [VOTE] Release Apache Arrow Flight SQL adapter for PostgreSQL
${version} - RC#{rc}
+
+Hi,
+
+I would like to propose the following release candidate (RC#{rc}) of
+Apache Arrow Flight SQL adapter for PostgreSQL version #{version}.
+
+This release candidate is based on commit: #{commit} [1]
+
+The source release rc#{rc} and changelog is hosted at [2].
+The binary artifacts are hosted at [3][4].
+
+Please download, verify checksums and signatures, build and run,
+and vote on the release. See [5] for how to validate a release
+candidate.
+
+The vote will be open for at least 24 hours because Apache Arrow
+Flight SQL adapter for PostgreSQL doesn't reach 1.0.0 yet.
+
+[ ] +1 Release this as Apache Arrow Flight SQL adapter for PostgreSQL
#{version}
+[ ] +0
+[ ] -1 Do not release this as Apache Arrow Flight SQL adapter for PostgreSQL
#{version}
+ because...
+
+[1]: https://github.com/apache/arrow-flight-sql-postgresql/commit/#{commit}
+[2]:
https://github.com/apache/arrow-flight-sql-postgresql/releases/tag/#{rc_tag}
+[3]: https://apache.jfrog.io/artifactory/arrow/debian-rc/
+[4]: https://apache.jfrog.io/artifactory/arrow/ubuntu-rc/
+[5]:
https://arrow.apache.org/flight-sql-postgresql/devel/release.html#how-to-verify-release-candidates
+ MAIL
+ end
+
+ namespace :publish do
+ desc "Publish to https://dist.apache.org/"
+ task :apache do
+ load_env
+ rc = detect_latest_rc(version)
+ rc_tag = "#{version}-rc#{rc}"
+ Dir.mktmpdir do |tmp|
+ sh("svn", "co",
+ "--depth=empty",
+ "https://dist.apache.org/repos/dist/release/arrow",
+ tmp)
+ release_dir = "#{tmp}/apache-arrow-flight-sql-postgresql-#{verison}"
+ mkdir_p(release_dir)
+ sh("gh", "release", "download",
+ "--dir", release_dir,
+ "--pattern", "#{archive_name}*",
+ "--repo", github_repository,
+ rc_tag)
+ sh("svn", "add", release_dir)
+ sh("svn", "ci", "-m", "#{project_label} #{version}", release_dir)
+ end
+ end
+
+ desc "Register a new release to https://reporter.apache.org/"
+ task :reporter do
+ sh("open", "https://reporter.apache.org/addrelease.html?arrow")
+ end
+
+ desc "Publish Linux packages"
+ task :linux do
+ rc = detect_latest_rc(version)
+ env = {
+ "UPLOAD_DEFAULT" => "0",
+ "UPLOAD_DEBIAN" => "1",
+ "UPLOAD_UBUNTU" => "1",
+ }
+ sh(env,
+ "#{arrow_source}/dev/release/post-02-binary.sh",
+ version,
+ rc.to_s)
+ end
+
+ desc "Tag #{version}"
+ task :tag do
+ load_env
+ rc = detect_latest_rc(version)
+ rc_tag = "#{version}-rc#{rc}"
+ sh("git", "tag",
+ "-a", version,
+ "-m", "#{project_label} #{version}",
+ "#{rc_tag}^{}")
+ if env_value("TAG_PUSH", "no") == "yes"
+ sh("git", "push", "upstream", version)
+ else
+ puts("Push #{version}:")
+ puts(" git push upstream #{version}")
+ end
+ end
+ end
+
+ desc "Publish the latest RC as a new release"
+ task :publish => [
+ "release:rc:publish:apache",
+ "release:rc:publish:reporter",
+ "release:rc:publish:linux",
+ "release:rc:publish:tag",
+ ]
+ end
+end
diff --git a/.gitignore b/dev/release/.env.example
similarity index 56%
copy from .gitignore
copy to dev/release/.env.example
index b75d024..11ff241 100644
--- a/.gitignore
+++ b/dev/release/.env.example
@@ -15,17 +15,21 @@
# specific language governing permissions and limitations
# under the License.
-/*.tar.gz
-/.cache/
-/Gemfile.lock
-/compile_commands.json
-/dev/release/apache-rat-0.13.jar
-/dev/release/dist
-/dev/release/filtered_rat.txt
-/dev/release/rat.xml
-/doc/build/
-/package/*/*.tar.gz
-/package/*/apt/build.sh
-/package/*/apt/env.sh
-/package/*/apt/repositories/
-/package/*/apt/tmp/
+# 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
+
+# The Artifactory API key to upload artifacts to Artifactory.
+#
+# This can be obtained by logging in to https://apache.jfrog.io with
+# your ASF credentials and generating an API key from your user profile.
+#
+# You must set this.
+#ARTIFACTORY_API_KEY=secret
diff --git a/src/afs.cc b/src/afs.cc
index bf78472..44f8d43 100644
--- a/src/afs.cc
+++ b/src/afs.cc
@@ -46,6 +46,10 @@ extern "C"
#undef Abs
+#if PG_VERSION_NUM >= 150000
+# define PGRN_HAVE_SHMEM_REQUEST_HOOK
+#endif
+
#include <arrow/buffer.h>
#include <arrow/builder.h>
#include <arrow/flight/server_middleware.h>
@@ -134,14 +138,17 @@ afs_sigusr1(SIGNAL_ARGS)
errno = errnoSaved;
}
+#ifdef PGRN_HAVE_SHMEM_REQUEST_HOOK
static shmem_request_hook_type PreviousShmemRequestHook = nullptr;
+#endif
static const char* LWLockTrancheName = "arrow-flight-sql: lwlock tranche";
void
afs_shmem_request_hook(void)
{
+#ifdef PGRN_HAVE_SHMEM_REQUEST_HOOK
if (PreviousShmemRequestHook)
PreviousShmemRequestHook();
-
+#endif
RequestNamedLWLockTranche(LWLockTrancheName, 1);
}
@@ -2378,7 +2385,7 @@ class Proxy : public WorkerProcessor {
break;
}
}
- return std::move(reader->schema());
+ return reader->schema();
}
std::random_device randomSeed_;
@@ -2452,7 +2459,7 @@ class MainProcessor : public Processor {
BackgroundWorkerHandle* start_server()
{
- BackgroundWorker worker = {0};
+ BackgroundWorker worker = {};
snprintf(worker.bgw_name, BGW_MAXLEN, "%s: server", Tag);
snprintf(worker.bgw_type, BGW_MAXLEN, "%s: server", Tag);
worker.bgw_flags = BGWORKER_SHMEM_ACCESS;
@@ -2485,7 +2492,7 @@ class MainProcessor : public Processor {
continue;
}
- BackgroundWorker worker = {0};
+ BackgroundWorker worker = {};
snprintf(
worker.bgw_name, BGW_MAXLEN, "%s: executor: %"
PRIu64, Tag, session->id);
snprintf(
@@ -2663,7 +2670,7 @@ class FlightSQLServer : public
arrow::flight::sql::FlightSqlServerBase {
ARROW_ASSIGN_OR_RAISE(auto ticket,
arrow::flight::sql::CreateStatementQueryTicket(query));
std::vector<arrow::flight::FlightEndpoint> endpoints{
- arrow::flight::FlightEndpoint{std::move(ticket), {}}};
+
arrow::flight::FlightEndpoint{arrow::flight::Ticket{std::move(ticket)}, {}}};
ARROW_ASSIGN_OR_RAISE(
auto result,
arrow::flight::FlightInfo::Make(*schema, descriptor,
endpoints, -1, -1));
@@ -2691,7 +2698,7 @@ class FlightSQLServer : public
arrow::flight::sql::FlightSqlServerBase {
arrow::Result<arrow::flight::sql::ActionCreatePreparedStatementResult>
CreatePreparedStatement(
const arrow::flight::ServerCallContext& context,
- const arrow::flight::sql::ActionCreatePreparedStatementRequest&
request)
+ const arrow::flight::sql::ActionCreatePreparedStatementRequest&
request) override
{
ARROW_ASSIGN_OR_RAISE(auto sessionID, session_id(context));
const auto& query = request.query;
@@ -2700,7 +2707,7 @@ class FlightSQLServer : public
arrow::flight::sql::FlightSqlServerBase {
arrow::Status ClosePreparedStatement(
const arrow::flight::ServerCallContext& context,
- const arrow::flight::sql::ActionClosePreparedStatementRequest&
request)
+ const arrow::flight::sql::ActionClosePreparedStatementRequest&
request) override
{
ARROW_ASSIGN_OR_RAISE(auto sessionID, session_id(context));
const auto& handle = request.prepared_statement_handle;
@@ -2720,7 +2727,7 @@ class FlightSQLServer : public
arrow::flight::sql::FlightSqlServerBase {
ARROW_ASSIGN_OR_RAISE(auto ticket,
arrow::flight::sql::CreateStatementQueryTicket(handle));
std::vector<arrow::flight::FlightEndpoint> endpoints{
- arrow::flight::FlightEndpoint{std::move(ticket), {}}};
+
arrow::flight::FlightEndpoint{arrow::flight::Ticket{std::move(ticket)}, {}}};
ARROW_ASSIGN_OR_RAISE(
auto result,
arrow::flight::FlightInfo::Make(*schema, descriptor,
endpoints, -1, -1));
@@ -2995,10 +3002,14 @@ _PG_init(void)
NULL,
NULL);
+#ifdef PGRN_HAVE_SHMEM_REQUEST_HOOK
PreviousShmemRequestHook = shmem_request_hook;
shmem_request_hook = afs_shmem_request_hook;
+#else
+ afs_shmem_request_hook();
+#endif
- BackgroundWorker worker = {0};
+ BackgroundWorker worker = {};
snprintf(worker.bgw_name, BGW_MAXLEN, "%s: main", Tag);
snprintf(worker.bgw_type, BGW_MAXLEN, "%s: main", Tag);
worker.bgw_flags = BGWORKER_SHMEM_ACCESS;