This is an automated email from the ASF dual-hosted git repository.
Fokko pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/parquet-java.git
The following commit(s) were added to refs/heads/master by this push:
new d2a165e4e Release: complete the Nexus secret rename and harden
cancel/publish (#3814)
d2a165e4e is described below
commit d2a165e4ee963f6ce36a2a237a6f76efb6d5418b
Author: Russell Spitzer <[email protected]>
AuthorDate: Tue Sep 22 23:48:35 2026 -0700
Release: complete the Nexus secret rename and harden cancel/publish (#3814)
The 2026-09-16 Cancel RC run for 1.19.0 rc9 failed with HTTP 401 because
release-cancel-rc.yml still read secrets.PARQUET_NEXUS_USER /
PARQUET_NEXUS_PASSWORD, which do not exist on apache/parquet-java. #3776
moved prepare-rc and publish to the ASF org-shared
NEXUS_STAGE_DEPLOYER_USER / NEXUS_STAGE_DEPLOYER_PW but missed cancel-rc,
the last two references in the tree. Nothing was cancelled: verification
is step 0, so the run aborted before dropping the staging repo or deleting
the SVN artifacts.
An absent secret expands to the empty string rather than failing, so the
credentials were present-but-blank and the first authenticated curl
reported only "error: 401". Add require_env and call it from all three
release scripts when DRY_RUN is not 1, so a missing credential is named
before any network call. Dry runs stay usable without secrets because
every authenticated call is already gated on DRY_RUN. _maven.sh had this
check for the deploy path only, which is why prepare-rc's Nexus 401 was
equally opaque.
Also apply #3787's tag-push ordering to publish-release.sh. It pushed the
final tag in step 3 and released the staging repo in step 4, so a Nexus
failure left a published release tag and the "Final release tag already
exists" guard then blocked the retry -- the same trap #3787 removed from
prepare-rc, where eight orphaned 1.19.0 RC tags accumulated. Keep git tag
-a in step 3 for the local reads that follow and move only the push to
step 5, immediately before the GitHub release that needs it on the remote.
Generated-by: Claude Opus 5 (1M context)
---
.github/workflows/release-cancel-rc.yml | 4 ++--
release/bin/cancel-rc.sh | 6 +++++
release/bin/prepare-rc.sh | 6 +++++
release/bin/publish-release.sh | 22 ++++++++++++++----
release/libs/_exec.sh | 21 +++++++++++++++++
release/tests/exec.bats | 40 +++++++++++++++++++++++++++++++++
6 files changed, 93 insertions(+), 6 deletions(-)
diff --git a/.github/workflows/release-cancel-rc.yml
b/.github/workflows/release-cancel-rc.yml
index 61c5fa328..a2290b1e8 100644
--- a/.github/workflows/release-cancel-rc.yml
+++ b/.github/workflows/release-cancel-rc.yml
@@ -70,8 +70,8 @@ jobs:
- name: Cancel Release Candidate
env:
DRY_RUN: ${{ inputs.dry_run && '1' || '0' }}
- NEXUS_USERNAME: ${{ secrets.PARQUET_NEXUS_USER }}
- NEXUS_PASSWORD: ${{ secrets.PARQUET_NEXUS_PASSWORD }}
+ NEXUS_USERNAME: ${{ secrets.NEXUS_STAGE_DEPLOYER_USER }}
+ NEXUS_PASSWORD: ${{ secrets.NEXUS_STAGE_DEPLOYER_PW }}
SVN_USERNAME: ${{ secrets.PARQUET_SVN_DEV_USERNAME }}
SVN_PASSWORD: ${{ secrets.PARQUET_SVN_DEV_PASSWORD }}
INPUT_VERSION: ${{ inputs.version }}
diff --git a/release/bin/cancel-rc.sh b/release/bin/cancel-rc.sh
index 37b12ffd5..768364c20 100755
--- a/release/bin/cancel-rc.sh
+++ b/release/bin/cancel-rc.sh
@@ -115,6 +115,12 @@ if [[ ${DRY_RUN:-1} -eq 1 ]]; then
step_summary ""
fi
+if [[ ${DRY_RUN:-1} -ne 1 ]]; then
+ if ! require_env NEXUS_USERNAME NEXUS_PASSWORD SVN_USERNAME SVN_PASSWORD;
then
+ exit 1
+ fi
+fi
+
if ! validate_and_extract_version "${version}"; then
print_error "Invalid version format: '${version}'"
exit 1
diff --git a/release/bin/prepare-rc.sh b/release/bin/prepare-rc.sh
index eb1b21399..0c16a7801 100755
--- a/release/bin/prepare-rc.sh
+++ b/release/bin/prepare-rc.sh
@@ -126,6 +126,12 @@ if [[ ${DRY_RUN:-1} -eq 1 ]]; then
step_summary ""
fi
+if [[ ${DRY_RUN:-1} -ne 1 ]]; then
+ if ! require_env NEXUS_USERNAME NEXUS_PASSWORD SVN_USERNAME SVN_PASSWORD;
then
+ exit 1
+ fi
+fi
+
if ! validate_and_extract_version "${version}"; then
print_error "Invalid version format: '${version}'. Expected: X.Y.Z"
exit 1
diff --git a/release/bin/publish-release.sh b/release/bin/publish-release.sh
index 32607c860..3af7758f7 100755
--- a/release/bin/publish-release.sh
+++ b/release/bin/publish-release.sh
@@ -128,6 +128,12 @@ if [[ ${DRY_RUN:-1} -eq 1 ]]; then
step_summary ""
fi
+if [[ ${DRY_RUN:-1} -ne 1 ]]; then
+ if ! require_env NEXUS_USERNAME NEXUS_PASSWORD SVN_USERNAME SVN_PASSWORD;
then
+ exit 1
+ fi
+fi
+
if ! validate_and_extract_version "${version}"; then
print_error "Invalid version format: '${version}'"
exit 1
@@ -246,15 +252,14 @@ else
fi
# ---------------------------------------------------------------------------
-# Step 3: Create final release tag
+# Step 3: Create final release tag locally (pushed in step 5)
# ---------------------------------------------------------------------------
step_summary ""
step_summary "### Release Tag"
exec_process git tag -a "${final_tag}" "${rc_commit}" -m "Release Apache
Parquet ${version}"
-exec_process git push origin "${final_tag}"
-step_summary "Created tag \`${final_tag}\` at \`${rc_commit}\`"
+step_summary "Created tag \`${final_tag}\` at \`${rc_commit}\` (pushed in step
5)"
# ---------------------------------------------------------------------------
# Step 4: Release Nexus staging repo
@@ -267,8 +272,17 @@ nexus_release_staging_repo "${staging_repo_id}" "Apache
Parquet ${version}"
step_summary "Released staging repository \`${staging_repo_id}\` to Maven
Central"
# ---------------------------------------------------------------------------
-# Step 5: Create GitHub Release
+# Step 5: Push the release tag and create the GitHub Release
# ---------------------------------------------------------------------------
+step_summary ""
+step_summary "### Tag Push"
+
+# Pushed here rather than with the tag creation in step 3: a Nexus failure in
+# step 4 would otherwise leave a published release tag, and the
+# "Final release tag already exists" guard then blocks the retry.
+exec_process git push origin "${final_tag}"
+step_summary "Pushed tag \`${final_tag}\`"
+
step_summary ""
step_summary "### GitHub Release"
diff --git a/release/libs/_exec.sh b/release/libs/_exec.sh
index 7920c0c5b..02bfe95d3 100644
--- a/release/libs/_exec.sh
+++ b/release/libs/_exec.sh
@@ -49,6 +49,27 @@ function _redact_secrets {
echo "${cmd_str}"
}
+# require_env <var>...
+# Fails unless every named variable is set and non-empty; a nonexistent
+# GitHub Actions secret expands to empty rather than unset.
+function require_env {
+ local missing=()
+ local var
+ for var in "$@"; do
+ if [[ -z "${!var:-}" ]]; then
+ missing+=("${var}")
+ fi
+ done
+
+ if [[ ${#missing[@]} -ne 0 ]]; then
+ print_error "Missing required environment variable(s): ${missing[*]}"
+ print_error "Under GitHub Actions this usually means the workflow
references a secret name that does not exist on this repository."
+ return 1
+ fi
+
+ return 0
+}
+
function exec_process {
local redacted
redacted=$(_redact_secrets "$@")
diff --git a/release/tests/exec.bats b/release/tests/exec.bats
index c5f3e66e0..40342562e 100644
--- a/release/tests/exec.bats
+++ b/release/tests/exec.bats
@@ -152,3 +152,43 @@ setup() {
rm -f "$tmpfile"
}
+
+# ---- require_env ----
+
+@test "require_env: succeeds when all variables are set" {
+ NEXUS_USERNAME="user"
+ NEXUS_PASSWORD="pass"
+ run require_env NEXUS_USERNAME NEXUS_PASSWORD
+ [ "$status" -eq 0 ]
+}
+
+@test "require_env: fails and names a variable that is set but empty" {
+ NEXUS_USERNAME=""
+ NEXUS_PASSWORD="pass"
+ run require_env NEXUS_USERNAME NEXUS_PASSWORD
+ [ "$status" -eq 1 ]
+ [[ "$output" == *"NEXUS_USERNAME"* ]]
+ [[ "$output" != *"NEXUS_PASSWORD"* ]]
+}
+
+@test "require_env: fails and names a variable that is unset" {
+ unset NEXUS_USERNAME
+ run require_env NEXUS_USERNAME
+ [ "$status" -eq 1 ]
+ [[ "$output" == *"NEXUS_USERNAME"* ]]
+}
+
+@test "require_env: reports every missing variable" {
+ unset NEXUS_USERNAME NEXUS_PASSWORD SVN_USERNAME
+ SVN_PASSWORD="pass"
+ run require_env NEXUS_USERNAME NEXUS_PASSWORD SVN_USERNAME SVN_PASSWORD
+ [ "$status" -eq 1 ]
+ [[ "$output" == *"NEXUS_USERNAME"* ]]
+ [[ "$output" == *"NEXUS_PASSWORD"* ]]
+ [[ "$output" == *"SVN_USERNAME"* ]]
+}
+
+@test "require_env: succeeds with no arguments" {
+ run require_env
+ [ "$status" -eq 0 ]
+}