Skip to content

Commit 6e1b630

Browse files
committed
chore: add post release scripts
1 parent f38f2c3 commit 6e1b630

File tree

4 files changed

+350
-58
lines changed

4 files changed

+350
-58
lines changed

.asf.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,10 @@ github:
1414
- id: jdaugherty
1515
type: User
1616
wait_timer: 0
17+
close:
18+
required_reviewers:
19+
- id: grails-committers
20+
type: Team
21+
- id: jdaugherty
22+
type: User
23+
wait_timer: 0
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
#!/bin/bash
2+
3+
#
4+
# Licensed to the Apache Software Foundation (ASF) under one
5+
# or more contributor license agreements. See the NOTICE file
6+
# distributed with this work for additional information
7+
# regarding copyright ownership. The ASF licenses this file
8+
# to you under the Apache License, Version 2.0 (the
9+
# "License"); you may not use this file except in compliance
10+
# with the License. You may obtain a copy of the License at
11+
#
12+
# https://www.apache.org/licenses/LICENSE-2.0
13+
#
14+
# Unless required by applicable law or agreed to in writing,
15+
# software distributed under the License is distributed on an
16+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17+
# KIND, either express or implied. See the License for the
18+
# specific language governing permissions and limitations
19+
# under the License.
20+
#
21+
22+
# ./releaseDistributions.sh <tag> <username> <password>
23+
24+
set -euo pipefail
25+
26+
if [[ $# -ne 3 ]]; then
27+
echo "Usage: $0 <tag> <username> <password>" >&2
28+
exit 1
29+
fi
30+
31+
RELEASE_TAG="$1"
32+
RELEASE_VERSION="${RELEASE_TAG#v}"
33+
SVN_USER="$2"
34+
SVN_PASS="$3"
35+
RELEASE_ROOT="https://dist.apache.org/repos/dist/release/incubator/grails/redis"
36+
DEV_ROOT="https://dist.apache.org/repos/dist/dev/incubator/grails/redis"
37+
38+
if [[ -z "${RELEASE_TAG}" ]]; then
39+
echo "❌ ERROR: Release Tag must not be empty." >&2
40+
exit 1
41+
fi
42+
if [[ -z "${SVN_USER}" ]]; then
43+
echo "❌ ERROR: Username must not be empty." >&2
44+
exit 1
45+
fi
46+
if [[ -z "${SVN_PASS}" ]]; then
47+
echo "❌ ERROR: Password must not be empty." >&2
48+
exit 1
49+
fi
50+
51+
svn_flags=(--non-interactive --trust-server-cert --username "${SVN_USER}" --password "${SVN_PASS}")
52+
53+
svn_exists() {
54+
local url="$1"
55+
svn ls "${svn_flags[@]}" --depth=empty "${url}" >/dev/null 2>&1
56+
}
57+
58+
old_release_folder="$(svn ls "${svn_flags[@]}" "${RELEASE_ROOT}" | awk -F/ 'NF{print $1; exit}')"
59+
if [[ -n "${old_release_folder}" ]]; then
60+
PRIOR_RELEASE_URL="${RELEASE_ROOT}/${old_release_folder}"
61+
echo "🗑️ Deleting old release folder: ${PRIOR_RELEASE_URL}"
62+
svn rm "${svn_flags[@]}" -m "Remove previous release ${old_release_folder}" "${PRIOR_RELEASE_URL}"
63+
echo "✅ Deleted old release folder"
64+
else
65+
echo "ℹ️ No existing release subfolder found under ${RELEASE_ROOT}"
66+
fi
67+
68+
DEV_VERSION_URL="$DEV_ROOT/${RELEASE_VERSION}"
69+
RELEASE_VERSION_URL="$RELEASE_ROOT/${RELEASE_VERSION}"
70+
71+
if ! svn_exists "${DEV_VERSION_URL}"; then
72+
echo "❌ ERROR: dev folder for ${RELEASE_VERSION} does not exist at: ${DEV_VERSION_URL}" >&2
73+
exit 2
74+
fi
75+
76+
if svn_exists "${RELEASE_VERSION_URL}"; then
77+
echo "❌ ERROR: release folder for ${RELEASE_VERSION} already exists at: ${RELEASE_VERSION_URL}" >&2
78+
exit 3
79+
fi
80+
81+
echo "🚀 Promoting ${DEV_VERSION_URL} -> ${RELEASE_VERSION_URL}"
82+
svn mv "${svn_flags[@]}" -m "Promote Apache Grails (incubating) ${RELEASE_VERSION} from dev to release" "${DEV_VERSION_URL}" "${RELEASE_VERSION_URL}"
83+
echo "✅ Promoted"

.github/scripts/releaseJarFiles.sh

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
#!/bin/bash
2+
3+
#
4+
# Licensed to the Apache Software Foundation (ASF) under one
5+
# or more contributor license agreements. See the NOTICE file
6+
# distributed with this work for additional information
7+
# regarding copyright ownership. The ASF licenses this file
8+
# to you under the Apache License, Version 2.0 (the
9+
# "License"); you may not use this file except in compliance
10+
# with the License. You may obtain a copy of the License at
11+
#
12+
# https://www.apache.org/licenses/LICENSE-2.0
13+
#
14+
# Unless required by applicable law or agreed to in writing,
15+
# software distributed under the License is distributed on an
16+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17+
# KIND, either express or implied. See the License for the
18+
# specific language governing permissions and limitations
19+
# under the License.
20+
#
21+
22+
# ./releaseJarFiles.sh <staging repo description> <username> <password>
23+
24+
set -euo pipefail
25+
26+
if [[ $# -ne 3 ]]; then
27+
echo "Usage: $0 <staging repo description> <username> <password>" >&2
28+
exit 1
29+
fi
30+
31+
NEXUS_URL="https://repository.apache.org"
32+
STAGING_DESCRIPTION="$1"
33+
NEXUS_USER="$2"
34+
NEXUS_PASS="$3"
35+
36+
if [[ -z "${STAGING_DESCRIPTION}" ]]; then
37+
echo "ERROR: Staging Description must not be empty." >&2
38+
exit 1
39+
fi
40+
if [[ -z "${NEXUS_USER}" ]]; then
41+
echo "ERROR: Username must not be empty." >&2
42+
exit 1
43+
fi
44+
if [[ -z "${NEXUS_PASS}" ]]; then
45+
echo "ERROR: Password must not be empty." >&2
46+
exit 1
47+
fi
48+
49+
nexusApi() {
50+
local request_method="$1"; shift
51+
local path="$1"; shift
52+
curl -fsS -u "${NEXUS_USER}:${NEXUS_PASS}" \
53+
-H 'Accept: application/json' \
54+
-H 'Content-Type: application/json' \
55+
-X "${request_method}" "${NEXUS_URL}/service/local/${path}" "$@"
56+
}
57+
58+
wait_for_promotion() {
59+
local repoId="$1"
60+
local timeout_s="${2:-600}" # default 10 minutes
61+
local interval_s="${3:-3}"
62+
local started
63+
started="$(date +%s)"
64+
65+
echo "Waiting for release promotion to complete (timeout ${timeout_s}s)…"
66+
67+
while :; do
68+
# 1) If any ERROR appears in activity, fail fast
69+
act="$(nexusApi GET "/staging/repository/${repoId}/activity" || true)"
70+
if [[ -n "$act" ]]; then
71+
err_count="$(jq -r '[.. | objects? | select(has("severity")) | select(.severity=="ERROR")] | length' <<<"$act" 2>/dev/null || echo 0)"
72+
if [[ "$err_count" != "0" ]]; then
73+
echo "ERROR: Staging activity contains failure(s). Aborting." >&2
74+
# Optionally dump recent relevant lines:
75+
jq -r '.. | objects? | select(has("severity")) | "\(.severity): \(.name // "event") - \(.message // "")"' <<<"$act" || true
76+
return 1
77+
fi
78+
fi
79+
80+
# 2) Check transitioning flag — when false after promote, action is done
81+
trans="$(nexusApi GET '/staging/profile_repositories' \
82+
| jq -r --arg r "$repoId" '.data[]? | select(.repositoryId==$r) | .transitioning' 2>/dev/null || echo "true")"
83+
84+
if [[ "$trans" == "false" ]]; then
85+
# sanity: make sure we actually saw some "release/promote" activity; otherwise keep waiting a bit
86+
if [[ -n "$act" ]]; then
87+
# did we see any promote/release-ish step?
88+
saw_promote="$(jq -r '
89+
[ .. | objects? | .name? // empty | ascii_downcase
90+
| select(test("release|promote|finish")) ] | length' <<<"$act" 2>/dev/null || echo 0)"
91+
if [[ "$saw_promote" -gt 0 ]]; then
92+
echo "Promotion appears complete."
93+
return 0
94+
fi
95+
fi
96+
fi
97+
98+
# timeout?
99+
now="$(date +%s)"
100+
if (( now - started >= timeout_s )); then
101+
echo "ERROR: Timed out waiting for promotion to complete." >&2
102+
# Show a short summary to aid debugging
103+
if [[ -n "$act" ]]; then
104+
echo "--- Recent activity snapshot ---"
105+
jq -r '.. | objects? | select(has("severity") or has("name")) | "\(.severity // "")\t\(.name // "")\t\(.message // "")"' <<<"$act" | tail -n 20 || true
106+
fi
107+
return 1
108+
fi
109+
110+
sleep "$interval_s"
111+
done
112+
}
113+
114+
repos_json="$(nexusApi GET '/staging/profile_repositories')"
115+
repoId="$(jq -r --arg d "${STAGING_DESCRIPTION}" '.data[] | select(.description==$d) | .repositoryId' <<<"${repos_json}")"
116+
profileId="$(jq -r --arg d "${STAGING_DESCRIPTION}" '.data[] | select(.description==$d) | .profileId' <<<"${repos_json}")"
117+
state="$(jq -r --arg d "${STAGING_DESCRIPTION}" '.data[] | select(.description==$d) | .type' <<<"${repos_json}")"
118+
119+
if [[ -z "${repoId}" || -z "${profileId}" ]]; then
120+
echo "ERROR: No staged repository found with description: ${STAGING_DESCRIPTION}" >&2
121+
exit 2
122+
fi
123+
echo "Found staged repo: ${repoId} (profile: ${profileId}, state: ${state})"
124+
if [[ "${state}" == "open" ]]; then
125+
echo "ERROR: Staged Repo is not closed: ${STAGING_DESCRIPTION}" >&2
126+
exit 3
127+
fi
128+
129+
if [[ "${state}" == "closed" ]]; then
130+
echo "Promoting (release) ${repoId}"
131+
nexusApi POST "/staging/profiles/${profileId}/promote" \
132+
--data "$(jq -n --arg r "${repoId}" --arg d "${STAGING_DESCRIPTION}" '{data:{stagedRepositoryId:$r,description:$d}}')"
133+
fi
134+
135+
wait_for_promotion "$repoId" 600 3
136+
137+
echo "Dropping staging repository ${repoId}"
138+
nexusApi POST "/staging/profiles/${profileId}/drop" \
139+
--data "$(jq -n --arg r "$repoId" --arg d "${STAGING_DESCRIPTION}" '{data:{stagedRepositoryId:$r,description:$d}}')"
140+
141+
echo "Done. Released ${repoId}."

0 commit comments

Comments
 (0)