diff --git a/.github/workflows/rc.yaml b/.github/workflows/rc.yaml new file mode 100644 index 0000000..9702de8 --- /dev/null +++ b/.github/workflows/rc.yaml @@ -0,0 +1,159 @@ +# 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. + +name: RC + +on: + push: + branches: + - "**" + - "!dependabot/**" + tags: + - "*-rc*" + pull_request: + +concurrency: + group: ${{ github.repository }}-${{ github.head_ref || github.sha }}-${{ github.workflow }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + target: + name: Target + runs-on: ubuntu-latest + timeout-minutes: 5 + outputs: + version: ${{ steps.detect.outputs.version }} + rc: ${{ steps.detect.outputs.rc }} + steps: + - name: Checkout + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - name: Detect + id: detect + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + if [ "${GITHUB_REF_TYPE}" = "tag" ]; then + version=${GITHUB_REF_NAME%-rc*} + version=${version#v} + rc=${GITHUB_REF_NAME#*-rc} + else + last_release_tag=$(gh release list \ + --exclude-drafts \ + --exclude-pre-releases \ + --jq '.[].tagName' \ + --json tagName \ + --limit 1) + if [ -n "${last_release_tag}" ]; then + version=${last_release_tag#v} + else + version=1.0.0 + fi + rc=$(date +%Y%m%d) + fi + echo "version=${version}" >> ${GITHUB_OUTPUT} + echo "rc=${rc}" >> ${GITHUB_OUTPUT} + + source: + name: Source + needs: target + runs-on: ubuntu-latest + timeout-minutes: 5 + env: + RC: ${{ needs.target.outputs.rc }} + VERSION: ${{ needs.target.outputs.version }} + steps: + - name: Checkout + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - name: Archive + run: | + id="apache-arrow-swift-${VERSION}" + tar_gz="${id}.tar.gz" + echo "TAR_GZ=${tar_gz}" >> ${GITHUB_ENV} + git archive HEAD --prefix "${id}/" --output "${tar_gz}" + sha256sum "${tar_gz}" > "${tar_gz}.sha256" + sha512sum "${tar_gz}" > "${tar_gz}.sha512" + - name: Upload + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: release-source + path: | + apache-arrow-swift-*.tar.gz* + - name: Audit + run: | + dev/release/run_rat.sh "${TAR_GZ}" + + verify: + name: Verify + needs: + - source + - target + runs-on: ubuntu-latest + timeout-minutes: 45 + env: + RC: ${{ needs.target.outputs.rc }} + VERSION: ${{ needs.target.outputs.version }} + steps: + - name: Checkout + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - name: Setup Swift + uses: swift-actions/setup-swift@682457186b71c25a884c45c06f859febbe259240 # v2.3.0 + with: + swift-version: "5.10" + - name: Download + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + with: + pattern: release-* + - name: Verify + env: + VERIFY_DEFAULT: 0 + VERIFY_SOURCE: 1 + run: | + mv release-*/* ./ + dev/release/verify_rc.sh "${VERSION}" "${RC}" + + upload: + name: Upload + needs: + - target + - verify + runs-on: ubuntu-latest + timeout-minutes: 5 + permissions: + contents: write + env: + RC: ${{ needs.target.outputs.rc }} + VERSION: ${{ needs.target.outputs.version }} + steps: + - name: Download + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + with: + pattern: release-* + - name: Upload + if: github.ref_type == 'tag' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh release create ${GITHUB_REF_NAME} \ + --generate-notes \ + --prerelease \ + --repo ${GITHUB_REPOSITORY} \ + --title "Apache Arrow Swift ${VERSION} RC${RC}" \ + --verify-tag \ + release-*/*.tar.gz* diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..8aa89c9 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,58 @@ +# 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. + +name: Release + +on: + push: + tags: + - "*" + - "!*-rc*" + +permissions: + contents: write + +env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + +jobs: + publish: + name: Publish + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - name: Download RC contents + run: | + set -x + latest_rc_tag=$(gh release list \ + --jq '.[].tagName' \ + --json tagName \ + --repo ${GITHUB_REPOSITORY} | \ + grep -F "${GITHUB_REF_NAME}-rc" | \ + head -n1) + gh release download ${latest_rc_tag} \ + --repo ${GITHUB_REPOSITORY} \ + --dir dists + - name: Create GitHub Release + run: | + version=${GITHUB_REF_NAME#v} + gh release create ${GITHUB_REF_NAME} \ + --generate-notes \ + --repo ${GITHUB_REPOSITORY} \ + --title "Apache Arrow Swift ${version}" \ + --verify-tag \ + dists/* diff --git a/.gitignore b/.gitignore index 6c315b8..65bfb48 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,7 @@ xcuserdata/ /dev/release/apache-rat-*.jar /dev/release/filtered_rat.txt /dev/release/rat.xml + +# Release +/apache-arrow-swift-*.tar.gz* +/dev/release/.env diff --git a/ci/scripts/build.sh b/ci/scripts/build.sh index 7acb359..043642d 100755 --- a/ci/scripts/build.sh +++ b/ci/scripts/build.sh @@ -37,14 +37,18 @@ rm -rf "${build_dir}" mkdir -p "${build_dir}" cp -a "${source_dir}" "${build_dir}/source" rm -rf "${build_dir}/source/.build" -mkdir -p /cache/swift-build -ln -s /cache/swift-build "${build_dir}/source/.build" +if [ -d /cache ]; then + mkdir -p /cache/swift-build + ln -s /cache/swift-build "${build_dir}/source/.build" +fi github_actions_group_end github_actions_group_begin "Generate data" data_gen_dir="${build_dir}/source/data-generator/swift-datagen" -export GOCACHE="/cache/go-build" -export GOMODCACHE="/cache/go-mod" +if [ -d /cache ]; then + export GOCACHE="/cache/go-build" + export GOMODCACHE="/cache/go-mod" +fi export GOPATH="${build_dir}" pushd "${data_gen_dir}" go get -d ./... diff --git a/dev/release/.env.example b/dev/release/.env.example new file mode 100644 index 0000000..c926902 --- /dev/null +++ b/dev/release/.env.example @@ -0,0 +1,33 @@ +# 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. + +# The GitHub token to upload artifacts to GitHub Release. +# +# You must set this. +#GH_TOKEN=secret +export GH_TOKEN + +# 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/README.md b/dev/release/README.md new file mode 100644 index 0000000..59461b6 --- /dev/null +++ b/dev/release/README.md @@ -0,0 +1,212 @@ + + +# Release + +## Overview + +1. Test the revision to be released +2. Prepare RC and vote (detailed later) +3. Publish (detailed later) +4. Announce the new release on the mailing list (detailed later) +5. Announce the new release on social media (detailed later) + +## Prepare release environment + +This step is needed only when you act as a release manager the first time. + +We use the following variables in multiple steps: + +* `GH_TOKEN`: GitHub personal access token to automate GitHub related + operations +* `GPG_KEY_ID`: PGP key ID that is used for signing official artifacts + by GnuPG + +We use `dev/release/.env` to share these variables in multiple +steps. You can use `dev/release/.env.example` as a template: + +```console +$ cp dev/release/.env{.example,} +$ chmod go-r dev/release/.env +$ editor dev/release/.env +``` + +See +https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens +how to prepare GitHub personal access token for `GH_TOKEN`. + +Note that you also need to install `gh` command because our scripts +use `gh` command to use GitHub API. See +https://github.com/cli/cli#installation how to install `gh` +command. + +If you don't have a PGP key for `GPG_KEY_ID`, see +https://infra.apache.org/release-signing.html#genegrate how to +generate your PGP key. + +Your PGP key must be registered to the followings: + + * https://dist.apache.org/repos/dist/dev/arrow/KEYS + * https://dist.apache.org/repos/dist/release/arrow/KEYS + +See the header comment of them how to add a PGP key. + +Apache arrow committers can update them by Subversion client with +their ASF account. e.g.: + +```console +$ svn co https://dist.apache.org/repos/dist/dev/arrow +$ cd arrow +$ head KEYS +(This shows how to update KEYS) +$ svn ci KEYS +``` + +## Prepare RC and vote + +You can use `dev/release/release_rc.sh`. + +Requirements to run `release_rc.sh`: + +* You must be an Apache Arrow committer or PMC member +* You must prepare your PGP key for signing + +Run `dev/release/release_rc.sh` on a working copy of +`git@github.com:apache/arrow-swift` not your fork: + +```console +$ git clone git@github.com:apache/arrow-swift.git +$ cd arrow-swift +$ dev/release/release_rc.sh ${VERSION} ${RC} +(Send a vote email to dev@arrow.apache.org. + You can use a draft shown by release_rc.sh for the email.) +``` + +Here is an example to release 21.0.0 RC0: + +```console +$ dev/release/release_rc.sh 21.0.0 0 +``` + +The arguments of `release_rc.sh` are the version and the RC number. If +RC0 has a problem, we'll increment the RC number such as RC1, RC2 and +so on. + +## Publish + +We need to do the followings to publish a new release: + +* Publish the source archive to apache.org + +Run `dev/release/release.sh` on a working copy of +`git@github.com:apache/arrow-swift` not your fork to publish the +source archive to apache.org: + +```console +$ dev/release/release.sh ${VERSION} ${RC} +``` + +Here is an example to release 21.0.0 RC0: + +```console +$ dev/release/release.sh 21.0.0 0 +``` + +Add the release to ASF's report database via [Apache Committee Report +Helper](https://reporter.apache.org/addrelease.html?arrow). + +## Announce the new release on the mailing list + +Send an email to "announce@apache.org" from your Apache email, CC'ing +dev@arrow.apache.org/user@arrow.apache.org. See an [example +post](https://lists.apache.org/thread/bxpt0r8kw0ltgywnylqdroskkt6966z4). + +``` +To: announce@apache.org +CC: dev@arrow.apache.org, user@arrow.apache.org +Subject: [ANNOUNCE] Apache Arrow Swift 21.0.0 released + +The Apache Arrow community is pleased to announce the Arrow Swift 21.0.0 +release. + +The release is available now. + +Source archive: + https://www.apache.org/dyn/closer.lua/arrow/apache-arrow-swift-21.0.0/ + +On Swift Package Index: + https://swiftpackageindex.com/apache/arrow + +Read the full changelog: + https://github.com/apache/arrow-swift/releases/tag/v21.0.0 + +What is Apache Arrow? +--------------------- + +Apache Arrow is a universal columnar format and multi-language toolbox +for fast data interchange and in-memory analytics. It houses a set of +canonical in-memory representations of flat and hierarchical data +along with multiple language-bindings for structure manipulation. It +also provides low-overhead streaming and batch messaging, zero-copy +interprocess communication (IPC), and vectorized in-memory analytics +libraries. + +Please report any feedback to the GitHub repository: + https://github.com/apache/arrow-swift/issues + https://github.com/apache/arrow-swift/discussions + +Regards, +The Apache Arrow community. +``` + +## Announce the new release on social media + +Make a post on our [BlueSky](https://bsky.app/profile/arrow.apache.org) and +[LinkedIn](https://www.linkedin.com/company/apache-arrow/) accounts. (Ask +your fellow PMC members for access if need be, or ask a PMC member to make the +post on your behalf.) The post should link to the blog post. See [example +BlueSky post](https://bsky.app/profile/arrow.apache.org/post/3lioi6ov5h22d) +and [example LinkedIn post](https://www.linkedin.com/posts/apache-arrow_apache-arrow-java-1820-release-activity-7298633716522758144-L71x). + +## Verify + +We have a script to verify a RC. + +You must install the following commands to use the script: + +* `curl` +* `go` +* `gpg` +* `shasum` or `sha256sum`/`sha512sum` +* `swift` 5.10 (6.0 or later don't work) +* `tar` + +To verify a RC, run the following command line: + +```console +$ dev/release/verify_rc.sh ${VERSION} ${RC} +``` + +Here is an example to verify the release 21.0.0 RC0: + +```console +$ dev/release/verify_rc.sh 21.0.0 0 +``` + +If the verification is successful, the message `RC looks good!` is shown. diff --git a/dev/release/release.sh b/dev/release/release.sh new file mode 100755 index 0000000..5a0832f --- /dev/null +++ b/dev/release/release.sh @@ -0,0 +1,115 @@ +#!/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_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +SOURCE_TOP_DIR="$(cd "${SOURCE_DIR}/../../" && pwd)" + +if [ "$#" -ne 2 ]; then + echo "Usage: $0 " + echo " e.g.: $0 21.0.0 0" + exit 1 +fi + +version="$1" +rc="$2" + +: "${RELEASE_DEFAULT:=1}" +: "${RELEASE_TAG:=${RELEASE_DEFAULT}}" +: "${RELEASE_UPLOAD:=${RELEASE_DEFAULT}}" +: "${RELEASE_CLEAN:=${RELEASE_DEFAULT}}" + +if [ ! -f "${SOURCE_DIR}/.env" ]; then + echo "You must create ${SOURCE_DIR}/.env" + echo "You can use ${SOURCE_DIR}/.env.example as template" + exit 1 +fi +. "${SOURCE_DIR}/.env" + +cd "${SOURCE_TOP_DIR}" + +git_origin_url="$(git remote get-url origin)" +repository="${git_origin_url#*github.com?}" +repository="${repository%.git}" +case "${git_origin_url}" in +git@github.com:apache/arrow-swift.git | https://github.com/apache/arrow-swift.git) + : # OK + ;; +*) + echo "This script must be ran with working copy of apache/arrow-swift." + echo "The origin's URL: ${git_origin_url}" + exit 1 + ;; +esac + +tag="v${version}" +rc_tag="${tag}-rc${rc}" +if [ "${RELEASE_TAG}" -gt 0 ]; then + echo "Tagging for release: ${tag}" + git tag -a -m "${version}" "${tag}" "${rc_tag}^{}" + git push origin "${tag}" +fi + +release_id="apache-arrow-swift-${version}" +source_archive="apache-arrow-swift-${version}.tar.gz" +dist_url="https://dist.apache.org/repos/dist/release/arrow" +dist_base_dir="dev/release/dist" +dist_dir="${dist_base_dir}/${release_id}" +if [ "${RELEASE_UPLOAD}" -gt 0 ]; then + echo "Checking out ${dist_url}" + rm -rf "${dist_base_dir}" + svn co --depth=empty "${dist_url}" "${dist_base_dir}" + gh release download "${rc_tag}" \ + --dir "${dist_dir}" \ + --pattern "${source_archive}*" \ + --repo "${repository}" \ + --skip-existing + + echo "Uploading to release/" + pushd "${dist_base_dir}" + svn add "${release_id}" + svn ci -m "Apache Arrow Swift ${version}" + popd + rm -rf "${dist_base_dir}" +fi + +if [ "${RELEASE_CLEAN}" -gt 0 ]; then + echo "Keep only the latest versions" + old_releases=$( + svn ls https://dist.apache.org/repos/dist/release/arrow/ | + grep -E '^apache-arrow-swift-' | + sort --version-sort --reverse | + tail -n +2 + ) + for old_release_version in ${old_releases}; do + echo "Remove old release ${old_release_version}" + svn \ + delete \ + -m "Remove old Apache Arrow Swift release: ${old_release_version}" \ + "https://dist.apache.org/repos/dist/release/arrow/${old_release_version}" + done +fi + +echo "Success! The release is available here:" +echo " https://dist.apache.org/repos/dist/release/arrow/${release_id}" +echo " https://swiftpackageindex.com/apache/arrow" +echo +echo "Add this release to ASF's report database:" +echo " https://reporter.apache.org/addrelease.html?arrow" diff --git a/dev/release/release_rc.sh b/dev/release/release_rc.sh new file mode 100755 index 0000000..ff5e5f0 --- /dev/null +++ b/dev/release/release_rc.sh @@ -0,0 +1,176 @@ +#!/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_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +SOURCE_TOP_DIR="$(cd "${SOURCE_DIR}/../../" && pwd)" + +if [ "$#" -ne 2 ]; then + echo "Usage: $0 " + echo " e.g.: $0 21.0.0 0" + exit 1 +fi + +version="$1" +rc="$2" + +: "${RELEASE_DEFAULT:=1}" +: "${RELEASE_PULL:=${RELEASE_DEFAULT}}" +: "${RELEASE_PUSH_TAG:=${RELEASE_DEFAULT}}" +: "${RELEASE_SIGN:=${RELEASE_DEFAULT}}" +: "${RELEASE_UPLOAD:=${RELEASE_DEFAULT}}" + +if [ ! -f "${SOURCE_DIR}/.env" ]; then + echo "You must create ${SOURCE_DIR}/.env" + echo "You can use ${SOURCE_DIR}/.env.example as template" + exit 1 +fi +. "${SOURCE_DIR}/.env" + +cd "${SOURCE_TOP_DIR}" + +if [ "${RELEASE_PULL}" -gt 0 ] || [ "${RELEASE_PUSH_TAG}" -gt 0 ]; then + git_origin_url="$(git remote get-url origin)" + case "${git_origin_url}" in + git@github.com:apache/arrow-swift.git | https://github.com/apache/arrow-swift.git) + : # OK + ;; + *) + echo "This script must be ran with working copy of apache/arrow-swift." + echo "The origin's URL: ${git_origin_url}" + exit 1 + ;; + esac +fi + +if [ "${RELEASE_PULL}" -gt 0 ]; then + echo "Ensure using the latest commit" + git checkout main + git pull --ff-only +fi + +rc_tag="v${version}-rc${rc}" +if [ "${RELEASE_PUSH_TAG}" -gt 0 ]; then + echo "Tagging for RC: ${rc_tag}" + git tag -a -m "${version} RC${rc}" "${rc_tag}" + git push origin "${rc_tag}" +fi + +rc_hash="$(git rev-list --max-count=1 "${rc_tag}")" + +artifacts_dir="apache-arrow-swift-${version}-rc${rc}" +signed_artifacts_dir="${artifacts_dir}-signed" + +if [ "${RELEASE_SIGN}" -gt 0 ]; then + git_origin_url="$(git remote get-url origin)" + repository="${git_origin_url#*github.com?}" + repository="${repository%.git}" + + echo "Looking for GitHub Actions workflow on ${repository}:${rc_tag}" + run_id="" + while true; do + sleep 10 + echo "Waiting for run to start..." + run_id=$(gh run list \ + --branch "${rc_tag}" \ + --jq ".[].databaseId" \ + --json 'databaseId' \ + --limit 1 \ + --repo "${repository}" \ + --workflow rc.yaml) + if [ -n "${run_id}" ]; then + break + fi + sleep 300 + done + + echo "Found GitHub Actions workflow with ID: ${run_id}" + gh run watch \ + --exit-status "${run_id}" \ + --interval 300 \ + --repo "${repository}" + + echo "Downloading artifacts from GitHub Releases" + gh release download "${rc_tag}" \ + --dir "${artifacts_dir}" \ + --repo "${repository}" \ + --skip-existing + + echo "Signing artifacts" + rm -rf "${signed_artifacts_dir}" + mkdir -p "${signed_artifacts_dir}" + for artifact in "${artifacts_dir}"/*; do + case "${artifact}" in + *.asc | *.sha256 | *.sha512) + continue + ;; + esac + gpg \ + --armor \ + --detach-sig \ + --local-user "${GPG_KEY_ID}" \ + --output "${signed_artifacts_dir}/$(basename "${artifact}").asc" \ + "${artifact}" + done + rm -rf "${artifacts_dir}" +fi + +if [ "${RELEASE_UPLOAD}" -gt 0 ]; then + echo "Uploading signature" + gh release upload "${rc_tag}" \ + --clobber \ + --repo "${repository}" \ + "${signed_artifacts_dir}"/*.asc +fi + +rm -rf "${signed_artifacts_dir}" + +echo +echo "Draft email for dev@arrow.apache.org mailing list" +echo "" +echo "---------------------------------------------------------" +cat < " + echo " e.g.: $0 21.0.0 0" + exit 1 +fi + +github_actions_group_begin() { + echo "::group::$1" + set -x +} + +github_actions_group_end() { + set +x + echo "::endgroup::" +} + +github_actions_group_begin "Prepare" + +VERSION="$1" +RC="$2" + +ARROW_DIST_BASE_URL="https://dist.apache.org/repos/dist/release/arrow" +DOWNLOAD_RC_BASE_URL="https://github.com/apache/arrow-swift/releases/download/v${VERSION}-rc${RC}" +ARCHIVE_BASE_NAME="apache-arrow-swift-${VERSION}" + +: "${VERIFY_DEFAULT:=1}" +: "${VERIFY_DOWNLOAD:=${VERIFY_DEFAULT}}" +: "${VERIFY_SIGN:=${VERIFY_DEFAULT}}" +: "${VERIFY_SOURCE:=${VERIFY_DEFAULT}}" + +VERIFY_SUCCESS=no + +setup_tmpdir() { + cleanup() { + # Go removes the write permissions for user from downloaded files. + chmod -R u+w "${VERIFY_TMPDIR}" || : + if [ "${VERIFY_SUCCESS}" = "yes" ]; then + rm -rf "${VERIFY_TMPDIR}" + else + echo "::endgroup::" + echo "Failed to verify release candidate. See ${VERIFY_TMPDIR} for details." + fi + } + + if [ -z "${VERIFY_TMPDIR:-}" ]; then + VERIFY_TMPDIR="$(mktemp -d -t "$1.XXXXX")" + trap cleanup EXIT + else + mkdir -p "${VERIFY_TMPDIR}" + fi +} + +download() { + curl \ + --fail \ + --location \ + --remote-name \ + --show-error \ + --silent \ + "$1" +} + +download_rc_file() { + if [ "${VERIFY_DOWNLOAD}" -gt 0 ]; then + download "${DOWNLOAD_RC_BASE_URL}/$1" + else + cp "${TOP_SOURCE_DIR}/$1" "$1" + fi +} + +import_gpg_keys() { + if [ "${VERIFY_SIGN}" -gt 0 ]; then + download "${ARROW_DIST_BASE_URL}/KEYS" + gpg --import KEYS + fi +} + +if type shasum >/dev/null 2>&1; then + sha256_verify="shasum -a 256 -c" + sha512_verify="shasum -a 512 -c" +else + sha256_verify="sha256sum -c" + sha512_verify="sha512sum -c" +fi + +fetch_archive() { + download_rc_file "${ARCHIVE_BASE_NAME}.tar.gz" + if [ "${VERIFY_SIGN}" -gt 0 ]; then + download_rc_file "${ARCHIVE_BASE_NAME}.tar.gz.asc" + gpg --verify "${ARCHIVE_BASE_NAME}.tar.gz.asc" "${ARCHIVE_BASE_NAME}.tar.gz" + fi + download_rc_file "${ARCHIVE_BASE_NAME}.tar.gz.sha256" + ${sha256_verify} "${ARCHIVE_BASE_NAME}.tar.gz.sha256" + download_rc_file "${ARCHIVE_BASE_NAME}.tar.gz.sha512" + ${sha512_verify} "${ARCHIVE_BASE_NAME}.tar.gz.sha512" +} + +ensure_source_directory() { + tar xf "${ARCHIVE_BASE_NAME}".tar.gz +} + +test_source_distribution() { + if [ "${VERIFY_SOURCE}" -le 0 ]; then + return 0 + fi + + "${TOP_SOURCE_DIR}/ci/scripts/build.sh" "$(pwd)" "$(pwd)/../build" + "${TOP_SOURCE_DIR}/ci/scripts/test.sh" "$(pwd)" "$(pwd)/../build" +} + +github_actions_group_end + +github_actions_group_begin "Setup temporary directory" +setup_tmpdir "arrow-swift-${VERSION}-${RC}" +echo "Working in sandbox ${VERIFY_TMPDIR}" +cd "${VERIFY_TMPDIR}" +github_actions_group_end + +github_actions_group_begin "Prepare source directory" +import_gpg_keys +fetch_archive +ensure_source_directory +github_actions_group_end + +pushd "${ARCHIVE_BASE_NAME}" + +github_actions_group_begin "Test source distribution" +test_source_distribution +github_actions_group_end + +popd + +VERIFY_SUCCESS=yes +echo "RC looks good!"