Skip to content

Commit e4f07cc

Browse files
authored
Release Hex & Rebar per OTP release (#1069)
1 parent 257164e commit e4f07cc

File tree

5 files changed

+216
-2
lines changed

5 files changed

+216
-2
lines changed

RELEASE.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ This document simply outlines the release process:
66

77
2. Ensure CHANGELOG is updated and add current date
88

9-
3. Update the local `release.sh` with the Elixir and OTP versions Hex should be built against.
9+
3. Update the local `scripts/release_hex.sh` with the Elixir and OTP versions Hex should be built against.
1010

1111
4. Commit changes above with title "Release vVERSION" and generate new tag
1212

@@ -16,7 +16,7 @@ This document simply outlines the release process:
1616

1717
7. Create GitHub release
1818

19-
8. Run the `release.sh` script and set the path to the private key for Elixir `ELIXIR_PEM=path/to/elixir.pem ./release.sh VERSION` where `VERSION` is the Hex version being released without a `v` prefix
19+
8. Run the `scripts/release_hex.sh` script and set the path to the private key for Elixir `ELIXIR_PEM=path/to/elixir.pem ./scripts/release_hex.sh VERSION` where `VERSION` is the Hex version being released without a `v` prefix
2020

2121
9. Purge "installs" key on Fastly dashboard
2222

scripts/publish_rebar.sh

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
#!/usr/bin/env bash
2+
# TODO: rename to scripts/release_rebar.sh. publish_rebar.sh is a temporary name for prettier git diff.
3+
4+
# Usage:
5+
#
6+
# $ ELIXIR_PEM=/path/to/elixir.pem \
7+
# HEX_FASTLY_KEY=... \
8+
# HEX_FASTLY_BUILDS_SERVICE_ID=... \
9+
# release_rebar.sh
10+
#
11+
# Unless ELIXIR_PEM is set, nothing is uploaded. After running, can be locally tested:
12+
#
13+
# $ (cd tmp && erl -S httpd)
14+
# $ HEX_BUILDS_URL=http://localhost:8000 mix local.rebar --force
15+
16+
set -e -u -o pipefail
17+
18+
function main {
19+
installs_dir="$PWD/tmp/installs"
20+
rebar_csv="${installs_dir}/rebar.csv"
21+
22+
rm -rf "${installs_dir}"
23+
mkdir "${installs_dir}"
24+
25+
# rebar.csv is always rebuilt from scratch. rebar builds are not reproducible, unfortunately.
26+
touch "${rebar_csv}"
27+
28+
# UPDATE THIS FOR EVERY RELEASE
29+
build 3.22.0 25.3.2.20 1.18.3 noble-20250404
30+
build 3.22.0 26.2.5.11 1.18.3 noble-20250404
31+
32+
build 3.24.0 25.3.2.20 1.18.3 noble-20250404
33+
build 3.24.0 26.2.5.11 1.18.3 noble-20250404
34+
build 3.24.0 27.3.3 1.18.3 noble-20250404
35+
36+
if [ -n "${ELIXIR_PEM}" ]; then
37+
openssl dgst -sha512 -sign "${ELIXIR_PEM}" "${rebar_csv}" | openssl base64 > "${rebar_csv}.signed"
38+
cd $installs_dir
39+
for path in $(find . -type f | sort); do
40+
path="${path#./}"
41+
echo "uploading ${path}..."
42+
s3up "${path}" "${path}"
43+
done
44+
45+
purge_key "${HEX_FASTLY_BUILDS_SERVICE_ID}" "installs"
46+
else
47+
echo "ELIXIR_PEM is empty, skipping"
48+
exit 1
49+
fi
50+
}
51+
52+
# $1 = rebar version
53+
# $2 = erlang version
54+
# $3 = elixir version
55+
# $4 = ubuntu version
56+
function build {
57+
rebar_version=$1
58+
otp_version=$2
59+
otp_release=${otp_version%%.*}
60+
elixir_version=$3
61+
ubuntu_version=$4
62+
63+
echo "Building ${rebar_version} ${otp_version} ${ubuntu_version}"
64+
mkdir -p "${installs_dir}/${elixir_version}"
65+
rebar="rebar3-${rebar_version}-otp-${otp_release}"
66+
67+
docker run -v "${installs_dir}/${elixir_version}":/installs hexpm/erlang:${otp_version}-ubuntu-${ubuntu_version} sh -c "\
68+
apt update && apt -y install git && \
69+
git clone https://github.com/erlang/rebar3.git -b ${rebar_version} && \
70+
cd rebar3 && \
71+
./bootstrap && \
72+
cp rebar3 /installs/$rebar
73+
"
74+
75+
sha=$(shasum -a 512 "${installs_dir}/${elixir_version}/$rebar")
76+
sha=($sha)
77+
echo "${rebar_version},${sha},${elixir_version},${otp_release}" >> "${rebar_csv}"
78+
}
79+
80+
# $1 = source
81+
# $2 = target
82+
function s3up {
83+
aws s3 cp "${1}" "s3://s3.hex.pm/installs/${2}" --acl public-read --cache-control "public, max-age=604800" --metadata "surrogate-key=installs"
84+
}
85+
86+
# $1 = source
87+
# $2 = target
88+
function s3down {
89+
aws s3 cp "s3://s3.hex.pm/installs/${1}" "${2}"
90+
}
91+
92+
# $1 = service
93+
# $2 = key
94+
function purge_key() {
95+
curl \
96+
--fail \
97+
-X POST \
98+
-H "Fastly-Key: ${HEX_FASTLY_KEY}" \
99+
-H "Accept: application/json" \
100+
-H "Content-Length: 0" \
101+
"https://api.fastly.com/service/$1/purge/$2"
102+
}
103+
104+
main $*

scripts/release_hex.sh

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
#!/usr/bin/env bash
2+
3+
# Usage:
4+
#
5+
# $ ELIXIR_PEM=/path/to/elixir.pem \
6+
# HEX_FASTLY_KEY=... \
7+
# HEX_FASTLY_BUILDS_SERVICE_ID=... \
8+
# release_hex.sh HEX_VERSION
9+
#
10+
# Unless ELIXIR_PEM is set, nothing is uploaded. After running, can be locally tested:
11+
#
12+
# $ (cd tmp && erl -S httpd)
13+
# $ HEX_BUILDS_URL=http://localhost:8000 mix local.hex --force
14+
15+
set -e -u -o pipefail
16+
17+
function main {
18+
hex_version=$1
19+
installs_dir="$PWD/tmp/installs"
20+
hex_csv="${installs_dir}/hex.csv"
21+
22+
rm -rf "${installs_dir}"
23+
mkdir "${installs_dir}"
24+
25+
s3down hex.csv "${hex_csv}"
26+
touch "${hex_csv}"
27+
sed -i.bak "/^${hex_version},/d" "${hex_csv}"
28+
29+
# UPDATE THIS FOR EVERY RELEASE
30+
build ${hex_version} 25.3.2.20 1.18.3 1.18.0 noble-20250404
31+
build ${hex_version} 26.2.5.11 1.18.3 1.18.0 noble-20250404
32+
build ${hex_version} 27.3.3 1.18.3 1.18.0 noble-20250404
33+
34+
build ${hex_version} 25.3.2.20 1.17.3 1.17.0 noble-20250404
35+
build ${hex_version} 26.2.5.11 1.17.3 1.17.0 noble-20250404
36+
build ${hex_version} 27.3.3 1.17.3 1.17.0 noble-20250404
37+
38+
rm -rf _build
39+
rm "${hex_csv}.bak"
40+
41+
if [ -n "${ELIXIR_PEM}" ]; then
42+
openssl dgst -sha512 -sign "${ELIXIR_PEM}" "${hex_csv}" | openssl base64 > "${hex_csv}.signed"
43+
44+
cd $installs_dir
45+
for path in $(find . -type f | sort); do
46+
path="${path#./}"
47+
echo "uploading ${path}..."
48+
s3up "${path}" "${path}"
49+
done
50+
51+
purge_key "${HEX_FASTLY_BUILDS_SERVICE_ID}" "installs"
52+
else
53+
echo "ELIXIR_PEM is empty, skipping"
54+
exit 1
55+
fi
56+
}
57+
58+
# $1 = hex version
59+
# $2 = erlang version
60+
# $3 = elixir version
61+
# $4 = saved elixir version
62+
# $5 = ubuntu version
63+
function build {
64+
hex_version=$1
65+
otp_version=$2
66+
otp_release=${otp_version%%.*}
67+
elixir_version=$3
68+
saved_elixir_version=$4
69+
ubuntu_version=$5
70+
71+
echo "Building ${elixir_version} ${otp_version} ${ubuntu_version}"
72+
rm -rf _build src/mix_safe_erl_term.erl
73+
hex_ez=hex-${hex_version}-otp-${otp_release}.ez
74+
75+
mkdir -p "$installs_dir/${saved_elixir_version}"
76+
docker run -v $(pwd):/hex hexpm/elixir:${elixir_version}-erlang-${otp_version}-ubuntu-${ubuntu_version} sh -c " \
77+
cd /hex && \
78+
MIX_ENV=prod mix archive.build -o ${hex_ez}"
79+
80+
mv "${hex_ez}" "${installs_dir}/${saved_elixir_version}/${hex_ez}"
81+
sha=$(shasum -a 512 "${installs_dir}/${saved_elixir_version}/${hex_ez}")
82+
sha=($sha)
83+
echo "${hex_version},${sha},${saved_elixir_version},${otp_release}" >> "${hex_csv}"
84+
}
85+
86+
# $1 = source
87+
# $2 = target
88+
function s3up {
89+
aws s3 cp "${1}" "s3://s3.hex.pm/installs/${2}" --acl public-read --cache-control "public, max-age=604800" --metadata "surrogate-key=installs"
90+
}
91+
92+
# $1 = source
93+
# $2 = target
94+
function s3down {
95+
aws s3 cp "s3://s3.hex.pm/installs/${1}" "${2}"
96+
}
97+
98+
# $1 = service
99+
# $2 = key
100+
function purge_key() {
101+
curl \
102+
--fail \
103+
-X POST \
104+
-H "Fastly-Key: ${HEX_FASTLY_KEY}" \
105+
-H "Accept: application/json" \
106+
-H "Content-Length: 0" \
107+
"https://api.fastly.com/service/$1/purge/$2"
108+
}
109+
110+
main $*

0 commit comments

Comments
 (0)