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/07 14:00:55 UTC

[arrow-adbc] branch main updated: chore(dev/release): add Windows release verification (#203)

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 7eddc72  chore(dev/release): add Windows release verification (#203)
7eddc72 is described below

commit 7eddc72a99ee63f8b3753c069c18c02089ecb202
Author: David Li <li...@gmail.com>
AuthorDate: Wed Dec 7 09:00:50 2022 -0500

    chore(dev/release): add Windows release verification (#203)
---
 .github/workflows/cpp.yml                | 114 ++++++++++++++++---------------
 c/driver/postgres/CMakeLists.txt         |   2 +-
 c/driver/sqlite/statement_reader.h       |   7 +-
 c/driver_manager/adbc_driver_manager.cc  |  11 +--
 ci/scripts/cpp_build.ps1                 |  65 ++++++++++++++++++
 ci/scripts/cpp_test.ps1                  |  65 ++++++++++++++++++
 ci/scripts/python_build.ps1              |  70 +++++++++++++++++++
 ci/scripts/python_test.ps1               |  61 +++++++++++++++++
 dev/release/verify-release-candidate.ps1 | 111 ++++++++++++++++++++++++++++++
 9 files changed, 443 insertions(+), 63 deletions(-)

diff --git a/.github/workflows/cpp.yml b/.github/workflows/cpp.yml
index df811c9..fc3bd0d 100644
--- a/.github/workflows/cpp.yml
+++ b/.github/workflows/cpp.yml
@@ -169,59 +169,61 @@ jobs:
       - name: Install Dependencies
         shell: cmd /C call {0}
         run: |
-          mamba install --file ci/conda_env_cpp.txt
-      - name: Build/Test SQLite3 Driver
-        shell: cmd /C call {0}
-        run: |
-          mkdir build\driver_sqlite
-          cd build\driver_sqlite
-          cmake -GNinja ..\..\c\drivers\sqlite -DADBC_BUILD_TESTS=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_PREFIX_PATH=%CONDA_PREFIX% -DADBC_BUILD_SHARED=ON -DADBC_BUILD_STATIC=OFF
-          if %errorlevel% neq 0 then exit /b %errorlevel%
-          cmake --build .
-          if %errorlevel% neq 0 then exit /b %errorlevel%
-          ctest --output-on-failure --no-tests=error
-          if %errorlevel% neq 0 then exit /b %errorlevel%
-          cd ..\..
-      - name: Build/Test Driver Manager
-        shell: cmd /C call {0}
-        run: |
-          mkdir build\driver_manager
-          cd build\driver_manager
-          cmake -GNinja ..\..\c\driver_manager -DADBC_BUILD_TESTS=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_PREFIX_PATH=%CONDA_PREFIX% -DADBC_BUILD_SHARED=ON -DADBC_BUILD_STATIC=OFF
-          if %errorlevel% neq 0 then exit /b %errorlevel%
-          cmake --build .
-          if %errorlevel% neq 0 then exit /b %errorlevel%
-          set PATH=%PATH%;${{ github.workspace }}\build\driver_sqlite
-          ctest --output-on-failure --no-tests=error
-          if %errorlevel% neq 0 then exit /b %errorlevel%
-          cd ..\..
-      - name: Build/Test SQLite Driver
-        shell: cmd /C call {0}
-        run: |
-          mkdir build\driver_sqlite
-          cd build\driver_sqlite
-          cmake -GNinja ..\..\c\driver\sqlite -DADBC_BUILD_TESTS=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_PREFIX_PATH=%CONDA_PREFIX% -DADBC_BUILD_SHARED=ON -DADBC_BUILD_STATIC=OFF
-          if %errorlevel% neq 0 then exit /b %errorlevel%
-          cmake --build .
-          dir
-          if %errorlevel% neq 0 then exit /b %errorlevel%
-          set PATH=%PATH%;${{ github.workspace }}\build\driver_sqlite
-          ctest --output-on-failure --no-tests=error
-          if %errorlevel% neq 0 then exit /b %errorlevel%
-          cd ..\..
-      - name: Build/Test Python Driver Manager
-        shell: cmd /C call {0}
-        run: |
-          cd python\adbc_driver_manager
-          pip install -e .
-          set PATH=%PATH%;${{ github.workspace }}\build\driver_sqlite
-          python -m pytest -vv
-          cd ..\..
-      - name: Build/Test Python Driver SQLite
-        shell: cmd /C call {0}
-        run: |
-          cd python\adbc_driver_sqlite
-          set ADBC_SQLITE_LIBRARY=${{ github.workspace }}\build\driver_sqlite\adbc_driver_sqlite.dll
-          pip install -e .
-          python -m pytest -vv
-          cd ..\..
+          mamba install --file ci/conda_env_cpp.txt --file ci/conda_env_python.txt
+      - name: Build Driver Manager
+        shell: pwsh
+        env:
+          BUILD_ALL: "0"
+          BUILD_DRIVER_MANAGER: "1"
+        run:
+          .\ci\scripts\cpp_build.ps1 $pwd $pwd\build
+      - name: Build Driver SQLite
+        shell: pwsh
+        env:
+          BUILD_ALL: "0"
+          BUILD_DRIVER_SQLITE: "1"
+        run:
+          .\ci\scripts\cpp_build.ps1 $pwd $pwd\build
+      - name: Test Driver Manager
+        shell: pwsh
+        env:
+          BUILD_ALL: "0"
+          BUILD_DRIVER_MANAGER: "1"
+        run:
+          .\ci\scripts\cpp_test.ps1 $pwd $pwd\build
+      - name: Test Driver SQLite
+        shell: pwsh
+        env:
+          BUILD_ALL: "0"
+          BUILD_DRIVER_SQLITE: "1"
+        run:
+          .\ci\scripts\cpp_test.ps1 $pwd $pwd\build
+
+      - name: Build Python Driver Manager
+        shell: pwsh
+        env:
+          BUILD_ALL: "0"
+          BUILD_DRIVER_MANAGER: "1"
+        run:
+          .\ci\scripts\python_build.ps1 $pwd $pwd\build
+      - name: Build Python Driver SQLite
+        shell: pwsh
+        env:
+          BUILD_ALL: "0"
+          BUILD_DRIVER_SQLITE: "1"
+        run:
+          .\ci\scripts\python_build.ps1 $pwd $pwd\build
+      - name: Test Python Driver Manager
+        shell: pwsh
+        env:
+          BUILD_ALL: "0"
+          BUILD_DRIVER_MANAGER: "1"
+        run:
+          .\ci\scripts\python_test.ps1 $pwd $pwd\build
+      - name: Test Python Driver SQLite
+        shell: pwsh
+        env:
+          BUILD_ALL: "0"
+          BUILD_DRIVER_SQLITE: "1"
+        run:
+          .\ci\scripts\python_test.ps1 $pwd $pwd\build
diff --git a/c/driver/postgres/CMakeLists.txt b/c/driver/postgres/CMakeLists.txt
index 62c587d..15c9712 100644
--- a/c/driver/postgres/CMakeLists.txt
+++ b/c/driver/postgres/CMakeLists.txt
@@ -29,7 +29,7 @@ include(CTest)
 if(WIN32)
   # XXX: for now, assume vcpkg
   find_package(PostgreSQL REQUIRED)
-  set(LIBPQ_LINK_LIBRARIES PostgreSQL::PostgreSQL)
+  set(LIBPQ_LINK_LIBRARIES PostgreSQL::PostgreSQL wsock32 ws2_32)
   set(LIBPQ_STATIC_LIBRARIES PostgreSQL::PostgreSQL)
   set(LIBPQ_INCLUDE_DIRS)
 else()
diff --git a/c/driver/sqlite/statement_reader.h b/c/driver/sqlite/statement_reader.h
index 3b1c425..1429503 100644
--- a/c/driver/sqlite/statement_reader.h
+++ b/c/driver/sqlite/statement_reader.h
@@ -28,7 +28,7 @@ extern "C" {
 #endif
 
 /// \brief Helper to manage binding data to a SQLite statement.
-struct AdbcSqliteBinder {
+struct ADBC_EXPORT AdbcSqliteBinder {
   // State
   struct ArrowSchema schema;
   struct ArrowArrayStream params;
@@ -40,16 +40,20 @@ struct AdbcSqliteBinder {
   int64_t next_row;
 };
 
+ADBC_EXPORT
 AdbcStatusCode AdbcSqliteBinderSetArray(struct AdbcSqliteBinder* binder,
                                         struct ArrowArray* values,
                                         struct ArrowSchema* schema,
                                         struct AdbcError* error);
+ADBC_EXPORT
 AdbcStatusCode AdbcSqliteBinderSetArrayStream(struct AdbcSqliteBinder* binder,
                                               struct ArrowArrayStream* values,
                                               struct AdbcError* error);
+ADBC_EXPORT
 AdbcStatusCode AdbcSqliteBinderBindNext(struct AdbcSqliteBinder* binder, sqlite3* conn,
                                         sqlite3_stmt* stmt, char* finished,
                                         struct AdbcError* error);
+ADBC_EXPORT
 void AdbcSqliteBinderRelease(struct AdbcSqliteBinder* binder);
 
 /// \brief Initialize an ArrowArrayStream from a sqlite3_stmt.
@@ -59,6 +63,7 @@ void AdbcSqliteBinderRelease(struct AdbcSqliteBinder* binder);
 /// \param[in] infer_rows How many rows to read to infer the Arrow schema.
 /// \param[out] stream The stream to export to.
 /// \param[out] error Error details, if needed.
+ADBC_EXPORT
 AdbcStatusCode AdbcSqliteExportReader(sqlite3* db, sqlite3_stmt* stmt,
                                       struct AdbcSqliteBinder* binder, size_t batch_size,
                                       struct ArrowArrayStream* stream,
diff --git a/c/driver_manager/adbc_driver_manager.cc b/c/driver_manager/adbc_driver_manager.cc
index 236073b..84a98d0 100644
--- a/c/driver_manager/adbc_driver_manager.cc
+++ b/c/driver_manager/adbc_driver_manager.cc
@@ -114,11 +114,12 @@ static AdbcStatusCode ReleaseDriver(struct AdbcDriver* driver, struct AdbcError*
   }
 
 #if defined(_WIN32)
-  if (!FreeLibrary(state->handle)) {
-    std::string message = "FreeLibrary() failed: ";
-    GetWinError(&message);
-    SetError(error, message);
-  }
+  // TODO(apache/arrow-adbc#204): causes tests to segfault
+  // if (!FreeLibrary(state->handle)) {
+  //   std::string message = "FreeLibrary() failed: ";
+  //   GetWinError(&message);
+  //   SetError(error, message);
+  // }
 #endif  // defined(_WIN32)
 
   driver->private_manager = nullptr;
diff --git a/ci/scripts/cpp_build.ps1 b/ci/scripts/cpp_build.ps1
new file mode 100755
index 0000000..b232e3f
--- /dev/null
+++ b/ci/scripts/cpp_build.ps1
@@ -0,0 +1,65 @@
+#!/usr/bin/env pwsh
+# 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.
+
+$ErrorActionPreference = "Stop"
+
+$SourceDir = $Args[0]
+$BuildDir = $Args[1]
+$InstallDir = if ($Args[2] -ne $null) { $Args[2] } else { Join-Path $BuildDir "local/" }
+
+$BuildAll = $env:BUILD_ALL -ne "0"
+$BuildDriverManager = ($BuildAll -and (-not ($env:BUILD_DRIVER_MANAGER -eq "0"))) -or ($env:BUILD_DRIVER_MANAGER -eq "1")
+$BuildDriverPostgres = ($BuildAll -and (-not ($env:BUILD_DRIVER_POSTGRES -eq "0"))) -or ($env:BUILD_DRIVER_POSTGRES -eq "1")
+$BuildDriverSqlite = ($BuildAll -and (-not ($env:BUILD_DRIVER_SQLITE -eq "0"))) -or ($env:BUILD_DRIVER_SQLITE -eq "1")
+
+function Build-Subproject {
+    $Subproject = $Args[0]
+    $SubprojectBuild = Join-Path $BuildDir $Subproject
+
+    echo "============================================================"
+    echo "Building $($Subproject)"
+    echo "============================================================"
+
+    New-Item -ItemType Directory -Force -Path $SubprojectBuild | Out-Null
+    Push-Location $SubprojectBuild
+
+    cmake `
+      $(Join-Path $SourceDir "c\$($Subproject)") `
+      -DADBC_BUILD_SHARED=ON `
+      -DADBC_BUILD_STATIC=OFF `
+      -DADBC_BUILD_TESTS=ON `
+      -DCMAKE_BUILD_TYPE=Debug `
+      -DCMAKE_INSTALL_PREFIX="$($InstallDir)" `
+      -DCMAKE_VERBOSE_MAKEFILE=ON
+    if (-not $?) { exit 1 }
+
+    cmake --build . --target install -j
+    if (-not $?) { exit 1 }
+
+    Pop-Location
+}
+
+if ($BuildDriverManager) {
+    Build-Subproject driver_manager
+}
+if ($BuildDriverPostgres) {
+    Build-Subproject driver\postgres
+}
+if ($BuildDriverSqlite) {
+    Build-Subproject driver\sqlite
+}
diff --git a/ci/scripts/cpp_test.ps1 b/ci/scripts/cpp_test.ps1
new file mode 100755
index 0000000..eefb4a7
--- /dev/null
+++ b/ci/scripts/cpp_test.ps1
@@ -0,0 +1,65 @@
+#!/usr/bin/env pwsh
+# 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.
+
+$ErrorActionPreference = "Stop"
+
+$SourceDir = $Args[0]
+$BuildDir = $Args[1]
+$InstallDir = if ($Args[2] -ne $null) { $Args[2] } else { Join-Path $BuildDir "local/" }
+
+$BuildAll = $env:BUILD_ALL -ne "0"
+$BuildDriverManager = ($BuildAll -and (-not ($env:BUILD_DRIVER_MANAGER -eq "0"))) -or ($env:BUILD_DRIVER_MANAGER -eq "1")
+$BuildDriverPostgres = ($BuildAll -and (-not ($env:BUILD_DRIVER_POSTGRES -eq "0"))) -or ($env:BUILD_DRIVER_POSTGRES -eq "1")
+$BuildDriverSqlite = ($BuildAll -and (-not ($env:BUILD_DRIVER_SQLITE -eq "0"))) -or ($env:BUILD_DRIVER_SQLITE -eq "1")
+
+$env:LD_LIBRARY_PATH += ":$($InstallDir)"
+$env:LD_LIBRARY_PATH += ":$($InstallDir)/bin"
+$env:LD_LIBRARY_PATH += ":$($InstallDir)/lib"
+$env:PATH += ";$($InstallDir)"
+$env:PATH += ";$($InstallDir)\bin"
+$env:PATH += ";$($InstallDir)\lib"
+
+echo $env:LD_LIBRARY_PATH
+echo $env:PATH
+
+function Build-Subproject {
+    $Subproject = $Args[0]
+    $SubprojectBuild = Join-Path $BuildDir $Subproject
+
+    echo "============================================================"
+    echo "Testing $($Subproject)"
+    echo "============================================================"
+
+    New-Item -ItemType Directory -Force -Path $SubprojectBuild | Out-Null
+    Push-Location $SubprojectBuild
+
+    ctest --output-on-failure --no-tests=error
+    if (-not $?) { exit 1 }
+
+    Pop-Location
+}
+
+if ($BuildDriverManager) {
+    Build-Subproject driver_manager
+}
+if ($BuildDriverPostgres) {
+    Build-Subproject driver\postgres
+}
+if ($BuildDriverSqlite) {
+    Build-Subproject driver\sqlite
+}
diff --git a/ci/scripts/python_build.ps1 b/ci/scripts/python_build.ps1
new file mode 100755
index 0000000..a1ffd57
--- /dev/null
+++ b/ci/scripts/python_build.ps1
@@ -0,0 +1,70 @@
+#!/usr/bin/env pwsh
+# 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.
+
+$ErrorActionPreference = "Stop"
+
+$SourceDir = $Args[0]
+$BuildDir = $Args[1]
+$InstallDir = if ($Args[2] -ne $null) { $Args[2] } else { Join-Path $BuildDir "local/" }
+
+$BuildAll = $env:BUILD_ALL -ne "0"
+$BuildDriverManager = ($BuildAll -and (-not ($env:BUILD_DRIVER_MANAGER -eq "0"))) -or ($env:BUILD_DRIVER_MANAGER -eq "1")
+$BuildDriverPostgres = ($BuildAll -and (-not ($env:BUILD_DRIVER_POSTGRES -eq "0"))) -or ($env:BUILD_DRIVER_POSTGRES -eq "1")
+$BuildDriverSqlite = ($BuildAll -and (-not ($env:BUILD_DRIVER_SQLITE -eq "0"))) -or ($env:BUILD_DRIVER_SQLITE -eq "1")
+
+function Build-Subproject {
+    $Subproject = $Args[0]
+    $SubprojectBuild = Join-Path $SourceDir "python\$($Subproject)"
+
+    echo "============================================================"
+    echo "Building $($Subproject)"
+    echo "============================================================"
+
+    pip install -e $SubprojectBuild
+    if (-not $?) { exit 1 }
+}
+
+if ($BuildDriverManager) {
+    Build-Subproject adbc_driver_manager
+}
+if ($BuildDriverPostgres) {
+    $env:ADBC_POSTGRES_LIBRARY = Get-Childitem `
+      -ErrorAction SilentlyContinue `
+      -Path $InstallDir `
+      -Recurse `
+      -Include "adbc_driver_postgres.dll","libadbc_driver_postgres.so" | % {$_.FullName}
+    echo $env:ADBC_POSTGRES_LIBRARY
+    if ($env:ADBC_POSTGRES_LIBRARY -eq $null) {
+        echo "Could not find libpq driver in $($InstallDir)"
+        exit 1
+    }
+    Build-Subproject adbc_driver_postgres
+}
+if ($BuildDriverSqlite) {
+    $env:ADBC_SQLITE_LIBRARY = Get-Childitem `
+      -ErrorAction SilentlyContinue `
+      -Path $InstallDir `
+      -Recurse `
+      -Include "adbc_driver_sqlite.dll","libadbc_driver_sqlite.so" | % {$_.FullName}
+    echo $env:ADBC_SQLITE_LIBRARY
+    if ($env:ADBC_SQLITE_LIBRARY -eq $null) {
+        echo "Could not find SQLite driver in $($InstallDir)"
+        exit 1
+    }
+    Build-Subproject adbc_driver_sqlite
+}
diff --git a/ci/scripts/python_test.ps1 b/ci/scripts/python_test.ps1
new file mode 100755
index 0000000..0bbb681
--- /dev/null
+++ b/ci/scripts/python_test.ps1
@@ -0,0 +1,61 @@
+#!/usr/bin/env pwsh
+# 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.
+
+$ErrorActionPreference = "Stop"
+
+$SourceDir = $Args[0]
+$BuildDir = $Args[1]
+$InstallDir = if ($Args[2] -ne $null) { $Args[2] } else { Join-Path $BuildDir "local/" }
+
+$BuildAll = $env:BUILD_ALL -ne "0"
+$BuildDriverManager = ($BuildAll -and (-not ($env:BUILD_DRIVER_MANAGER -eq "0"))) -or ($env:BUILD_DRIVER_MANAGER -eq "1")
+$BuildDriverPostgres = ($BuildAll -and (-not ($env:BUILD_DRIVER_POSTGRES -eq "0"))) -or ($env:BUILD_DRIVER_POSTGRES -eq "1")
+$BuildDriverSqlite = ($BuildAll -and (-not ($env:BUILD_DRIVER_SQLITE -eq "0"))) -or ($env:BUILD_DRIVER_SQLITE -eq "1")
+
+function Build-Subproject {
+    $Subproject = $Args[0]
+    $SubprojectBuild = Join-Path $SourceDir "python\$($Subproject)"
+
+    echo "============================================================"
+    echo "Testing $($Subproject)"
+    echo "============================================================"
+
+    python -m pytest -vv $SubprojectBuild
+    if (-not $?) { exit 1 }
+}
+
+if ($BuildDriverManager) {
+    $SqliteDir = Get-Childitem `
+      -ErrorAction SilentlyContinue `
+      -Path $InstallDir `
+      -Recurse `
+      -Include "adbc_driver_sqlite.dll","libadbc_driver_sqlite.so" | Split-Path -Parent
+    if ($SqliteDir -eq $null) {
+        echo "Could not find SQLite driver in $($InstallDir)"
+        exit 1
+    }
+    $env:LD_LIBRARY_PATH += ":$($SqliteDir)"
+    $env:PATH += ";$($SqliteDir)"
+    Build-Subproject adbc_driver_manager
+}
+if ($BuildDriverPostgres) {
+    Build-Subproject adbc_driver_postgres
+}
+if ($BuildDriverSqlite) {
+    Build-Subproject adbc_driver_sqlite
+}
diff --git a/dev/release/verify-release-candidate.ps1 b/dev/release/verify-release-candidate.ps1
new file mode 100755
index 0000000..30674fb
--- /dev/null
+++ b/dev/release/verify-release-candidate.ps1
@@ -0,0 +1,111 @@
+#!/usr/bin/env pwsh
+#
+# 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.
+
+# Expects PowerShell 7 but also tested with PowerShell 5.1 (built into
+# Windows 7+). Works on Linux!
+
+# To reuse build artifacts between runs set ARROW_TMPDIR environment variable to
+# a directory where the temporary files should be placed to, note that this
+# directory is not cleaned up automatically.
+
+$ErrorActionPreference = "Stop"
+
+if ($env:VERBOSE) {
+    Set-PSDebug -Trace 1
+}
+
+if ($args.Count -eq 0) {
+    $version = "HEAD"
+    $SourceKind = "local"
+} elseif ($args.Count -eq 2) {
+    $version = $args[0]
+    $SourceKind = "tarball"
+} else {
+    $script = Split-Path $PSCommandPath -leaf
+    echo @"
+Usage:
+  Verify release candidate:
+    $($script) X.Y.Z RC_NUMBER
+  Verify current checkout:
+    $($script)
+
+Assumes Mamba is set up and available on the path.
+"@
+    exit 1
+}
+
+function Show-Header {
+    echo ""
+    echo "============================================================"
+    echo $args[0]
+    echo "============================================================"
+}
+
+Show-Header "Create Temporary Directory"
+if ($env:ARROW_TMPDIR -eq $null) {
+    $ArrowTempDir = New-TemporaryFile | % { $_.FullName }
+    Remove-Item -Force $ArrowTempDir
+} else {
+    $ArrowTempDir = $env:ARROW_TMPDIR
+}
+New-Item -ItemType Directory -Force -Path $ArrowTempDir | Out-Null
+
+echo "Using $($ArrowTempDir)"
+
+Show-Header "Ensure Source Directory"
+
+if ($SourceKind -eq "local") {
+    $ArrowSourceDir = Join-Path $PSScriptRoot "..\.." | Resolve-Path | % { $_.Path }
+} else {
+    exit 1
+}
+
+echo "Using $($ArrowSourceDir)"
+
+Show-Header "Create Conda Environment"
+
+mamba create -c conda-forge -f -y -p $(Join-Path $ArrowTempDir conda-env) `
+  --file $(Join-Path $ArrowSourceDir ci\conda_env_cpp.txt) `
+  --file $(Join-Path $ArrowSourceDir ci\conda_env_python.txt)
+
+Invoke-Expression $(conda shell.powershell hook | Out-String)
+conda activate $(Join-Path $ArrowTempDir conda-env)
+
+Show-Header "Verify C/C++ Sources"
+
+$CppBuildDir = Join-Path $ArrowTempDir cpp-build
+New-Item -ItemType Directory -Force -Path $CppBuildDir | Out-Null
+
+& $(Join-Path $ArrowSourceDir ci\scripts\cpp_build.ps1) $ArrowSourceDir $CppBuildDir
+if (-not $?) { exit 1 }
+
+$env:BUILD_DRIVER_POSTGRES = "0"
+& $(Join-Path $ArrowSourceDir ci\scripts\cpp_test.ps1) $ArrowSourceDir $CppBuildDir
+if (-not $?) { exit 1 }
+$env:BUILD_DRIVER_POSTGRES = "1"
+
+Show-Header "Verify Python Sources"
+
+& $(Join-Path $ArrowSourceDir ci\scripts\python_build.ps1) $ArrowSourceDir $CppBuildDir
+if (-not $?) { exit 1 }
+
+& $(Join-Path $ArrowSourceDir ci\scripts\python_test.ps1) $ArrowSourceDir $CppBuildDir
+if (-not $?) { exit 1 }
+
+Show-Header "Release candidate looks good!"