Skip to content

Commit a81d206

Browse files
authored
Merge pull request #1299 from supertokens/ci/jre-zips
ci: add workflow to create zip files
2 parents 07ac3ff + 6d3c820 commit a81d206

6 files changed

Lines changed: 456 additions & 64 deletions

File tree

Lines changed: 286 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,286 @@
1+
#!/usr/bin/env bash
2+
3+
set -Eeuo pipefail
4+
5+
required_variables=(
6+
CORE_VERSION
7+
PLUGIN_INTERFACE_VERSION
8+
POSTGRESQL_VERSION
9+
S3_BUCKET
10+
)
11+
12+
for variable in "${required_variables[@]}"; do
13+
if [[ -z "${!variable:-}" ]]; then
14+
echo "Missing required environment variable: ${variable}" >&2
15+
exit 1
16+
fi
17+
done
18+
19+
version_pattern='^[0-9]+\.[0-9]+\.[0-9]+$'
20+
for version in "$CORE_VERSION" "$PLUGIN_INTERFACE_VERSION" "$POSTGRESQL_VERSION"; do
21+
if [[ ! "$version" =~ $version_pattern ]]; then
22+
echo "Expected a stable X.Y.Z version, received: ${version}" >&2
23+
exit 1
24+
fi
25+
done
26+
27+
S3_JAR_PREFIX="${S3_JAR_PREFIX:-core-jars}"
28+
S3_JRE_PREFIX="${S3_JRE_PREFIX:-core-runtime/jre}"
29+
S3_PACKAGE_PREFIX="${S3_PACKAGE_PREFIX:-packages/v1}"
30+
S3_JAR_PREFIX="${S3_JAR_PREFIX#/}"
31+
S3_JAR_PREFIX="${S3_JAR_PREFIX%/}"
32+
S3_JRE_PREFIX="${S3_JRE_PREFIX#/}"
33+
S3_JRE_PREFIX="${S3_JRE_PREFIX%/}"
34+
S3_PACKAGE_PREFIX="${S3_PACKAGE_PREFIX#/}"
35+
S3_PACKAGE_PREFIX="${S3_PACKAGE_PREFIX%/}"
36+
37+
ROOT_DIR="${ROOT_DIR:-$PWD}"
38+
CORE_DIR="${ROOT_DIR}/supertokens-core"
39+
PLUGIN_INTERFACE_DIR="${ROOT_DIR}/supertokens-plugin-interface"
40+
POSTGRESQL_DIR="${ROOT_DIR}/supertokens-postgresql-plugin"
41+
42+
for path in \
43+
"${CORE_DIR}/config.yaml" \
44+
"${CORE_DIR}/install" \
45+
"${CORE_DIR}/install.bat" \
46+
"${CORE_DIR}/LICENSE.md" \
47+
"${POSTGRESQL_DIR}/config.yaml"; do
48+
if [[ ! -f "$path" ]]; then
49+
echo "Missing package source file: ${path}" >&2
50+
exit 1
51+
fi
52+
done
53+
54+
version_at_least() {
55+
[[ "$(printf '%s\n%s\n' "$1" "$2" | sort -V | tail -1)" == "$1" ]]
56+
}
57+
58+
if version_at_least "$CORE_VERSION" "11.0.0"; then
59+
JRE_MAJOR="21"
60+
JRE_VERSION="21.0.7"
61+
else
62+
JRE_MAJOR="15"
63+
JRE_VERSION="15.0.1"
64+
fi
65+
66+
WORK_DIR="$(mktemp -d)"
67+
trap 'rm -rf "$WORK_DIR"' EXIT
68+
69+
CORE_JAR_KEY="${S3_JAR_PREFIX}/supertokens-core/v${CORE_VERSION}/core-${CORE_VERSION}.jar"
70+
CLI_JAR_KEY="${S3_JAR_PREFIX}/supertokens-core/v${CORE_VERSION}/cli.jar"
71+
DOWNLOADER_JAR_KEY="${S3_JAR_PREFIX}/supertokens-core/v${CORE_VERSION}/downloader.jar"
72+
EE_JAR_KEY="${S3_JAR_PREFIX}/supertokens-core/v${CORE_VERSION}/ee.jar"
73+
PLUGIN_INTERFACE_JAR_KEY="${S3_JAR_PREFIX}/supertokens-plugin-interface/v${PLUGIN_INTERFACE_VERSION}/plugin-interface-${PLUGIN_INTERFACE_VERSION}.jar"
74+
POSTGRESQL_JAR_KEY="${S3_JAR_PREFIX}/supertokens-postgresql-plugin/v${POSTGRESQL_VERSION}/postgresql-plugin-${POSTGRESQL_VERSION}.jar"
75+
release_manifest_key="${S3_PACKAGE_PREFIX}/releases/core-${CORE_VERSION}.json"
76+
77+
download_object() {
78+
local key="$1"
79+
local destination="$2"
80+
81+
mkdir -p "$(dirname "$destination")"
82+
aws s3 cp "s3://${S3_BUCKET}/${key}" "$destination" --only-show-errors
83+
}
84+
85+
object_state() {
86+
local key="$1"
87+
local error_file="${WORK_DIR}/head-object-error"
88+
89+
if aws s3api head-object --bucket "$S3_BUCKET" --key "$key" >/dev/null 2>"$error_file"; then
90+
printf 'exists'
91+
elif grep -Eq '\((404|NoSuchKey|NotFound)\)' "$error_file"; then
92+
printf 'missing'
93+
else
94+
cat "$error_file" >&2
95+
return 1
96+
fi
97+
}
98+
99+
if [[ "$(object_state "$release_manifest_key")" == "exists" ]]; then
100+
existing_release_manifest="${WORK_DIR}/existing-core-${CORE_VERSION}.json"
101+
download_object "$release_manifest_key" "$existing_release_manifest"
102+
existing_tuple="$(jq -r '[.core, .plugin, .pluginInterface] | join("/")' "$existing_release_manifest")"
103+
requested_tuple="${CORE_VERSION}/${POSTGRESQL_VERSION}/${PLUGIN_INTERFACE_VERSION}"
104+
if [[ "$existing_tuple" != "$requested_tuple" ]]; then
105+
echo "Release ${CORE_VERSION} is already published with tuple ${existing_tuple}" >&2
106+
exit 1
107+
fi
108+
fi
109+
110+
package_keys='{}'
111+
platforms=(mac windows linux linux-arm)
112+
113+
for platform in "${platforms[@]}"; do
114+
if [[ "$platform" == "linux-arm" && "$JRE_MAJOR" == "12" ]]; then
115+
continue
116+
fi
117+
118+
staging="${WORK_DIR}/staging-${platform}"
119+
package_root="${staging}/supertokens"
120+
mkdir -p \
121+
"${package_root}/core" \
122+
"${package_root}/cli" \
123+
"${package_root}/downloader" \
124+
"${package_root}/plugin" \
125+
"${package_root}/plugin-interface" \
126+
"${package_root}/jre"
127+
128+
download_object "$CORE_JAR_KEY" "${package_root}/core/core-${CORE_VERSION}.jar"
129+
download_object "$CLI_JAR_KEY" "${package_root}/cli/cli.jar"
130+
download_object "$DOWNLOADER_JAR_KEY" "${package_root}/downloader/downloader.jar"
131+
download_object "$PLUGIN_INTERFACE_JAR_KEY" "${package_root}/plugin-interface/plugin-interface-${PLUGIN_INTERFACE_VERSION}.jar"
132+
download_object "$POSTGRESQL_JAR_KEY" "${package_root}/plugin/postgresql-plugin-${POSTGRESQL_VERSION}.jar"
133+
134+
if [[ "$(object_state "$EE_JAR_KEY")" == "exists" ]]; then
135+
if [[ ! -f "${CORE_DIR}/ee/LICENSE.md" ]]; then
136+
echo "The EE JAR exists but ${CORE_DIR}/ee/LICENSE.md is missing" >&2
137+
exit 1
138+
fi
139+
download_object "$EE_JAR_KEY" "${package_root}/ee/ee.jar"
140+
cp "${CORE_DIR}/ee/LICENSE.md" "${package_root}/ee/LICENSE.md"
141+
fi
142+
143+
jre_archive_key="${S3_JRE_PREFIX}/${JRE_VERSION}/${platform}.tar.gz"
144+
jre_checksum_key="${jre_archive_key}.sha256"
145+
jre_archive="${WORK_DIR}/${JRE_VERSION}-${platform}.tar.gz"
146+
jre_checksum="${jre_archive}.sha256"
147+
download_object "$jre_archive_key" "$jre_archive"
148+
download_object "$jre_checksum_key" "$jre_checksum"
149+
expected_jre_checksum="$(cut -d ' ' -f 1 "$jre_checksum")"
150+
actual_jre_checksum="$(sha256sum "$jre_archive" | cut -d ' ' -f 1)"
151+
if [[ ! "$expected_jre_checksum" =~ ^[a-fA-F0-9]{64}$ || "$expected_jre_checksum" != "$actual_jre_checksum" ]]; then
152+
echo "JRE checksum mismatch for ${jre_archive_key}" >&2
153+
exit 1
154+
fi
155+
tar -xzf "$jre_archive" -C "${package_root}/jre"
156+
157+
if [[ "$platform" == "linux" || "$platform" == "linux-arm" ]]; then
158+
java_description="$(file -Lb "${package_root}/jre/bin/java")"
159+
if [[ "$platform" == "linux" && "$java_description" != *"x86-64"* ]]; then
160+
echo "Expected an x86-64 Linux JRE, found: ${java_description}" >&2
161+
exit 1
162+
fi
163+
if [[ "$platform" == "linux-arm" && "$java_description" != *"aarch64"* ]]; then
164+
echo "Expected an AArch64 Linux JRE, found: ${java_description}" >&2
165+
exit 1
166+
fi
167+
fi
168+
169+
install_file="install"
170+
if [[ "$platform" == "windows" ]]; then
171+
install_file="install.bat"
172+
fi
173+
cp "${CORE_DIR}/${install_file}" "${package_root}/${install_file}"
174+
chmod 755 "${package_root}/${install_file}"
175+
cp "${CORE_DIR}/LICENSE.md" "${package_root}/LICENSE.md"
176+
{
177+
cat "${CORE_DIR}/config.yaml"
178+
printf '\n\n'
179+
cat "${POSTGRESQL_DIR}/config.yaml"
180+
} > "${package_root}/config.yaml"
181+
cp "${package_root}/config.yaml" "${package_root}/config.yaml.original"
182+
cat > "${package_root}/version.yaml" <<EOF
183+
core_version: ${CORE_VERSION}
184+
plugin_interface_version: ${PLUGIN_INTERFACE_VERSION}
185+
plugin_version: ${POSTGRESQL_VERSION}
186+
plugin_name: postgresql
187+
EOF
188+
189+
for legacy_file in INSTALLATION_INSTRUCTIONS.txt SuperTokensLicense.pdf OpenSourceLicenses.pdf; do
190+
if [[ -f "${CORE_DIR}/${legacy_file}" ]]; then
191+
cp "${CORE_DIR}/${legacy_file}" "${package_root}/${legacy_file}"
192+
fi
193+
done
194+
195+
find "$staging" -exec touch -h -t 198001010000 {} +
196+
zip_path="${WORK_DIR}/supertokens-${platform}.zip"
197+
(
198+
cd "$staging"
199+
find . -print | LC_ALL=C sort | zip -X -y -q "$zip_path" -@
200+
)
201+
202+
package_key="${S3_PACKAGE_PREFIX}/core-${CORE_VERSION}/${platform}.zip"
203+
checksum="$(sha256sum "$zip_path" | cut -d ' ' -f 1)"
204+
checksum_path="${WORK_DIR}/${platform}.sha256"
205+
manifest_path="${WORK_DIR}/${platform}.manifest.json"
206+
printf '%s %s.zip\n' "$checksum" "$platform" > "$checksum_path"
207+
jq -n \
208+
--arg packageKey "$package_key" \
209+
--arg sha256 "$checksum" \
210+
--arg core "$CORE_VERSION" \
211+
--arg plugin "$POSTGRESQL_VERSION" \
212+
--arg pluginInterface "$PLUGIN_INTERFACE_VERSION" \
213+
--arg os "$platform" \
214+
--arg jreVersion "$JRE_VERSION" \
215+
--arg coreJarKey "$CORE_JAR_KEY" \
216+
--arg cliJarKey "$CLI_JAR_KEY" \
217+
--arg downloaderJarKey "$DOWNLOADER_JAR_KEY" \
218+
--arg pluginInterfaceJarKey "$PLUGIN_INTERFACE_JAR_KEY" \
219+
--arg postgresqlJarKey "$POSTGRESQL_JAR_KEY" \
220+
--arg jreArchiveKey "$jre_archive_key" \
221+
--argjson size "$(stat -c %s "$zip_path")" \
222+
'{
223+
packageKey: $packageKey,
224+
sha256: $sha256,
225+
size: $size,
226+
tuple: {
227+
core: $core,
228+
plugin: $plugin,
229+
pluginInterface: $pluginInterface,
230+
os: $os,
231+
jreVersion: $jreVersion
232+
},
233+
inputs: {
234+
coreJar: $coreJarKey,
235+
cliJar: $cliJarKey,
236+
downloaderJar: $downloaderJarKey,
237+
pluginInterfaceJar: $pluginInterfaceJarKey,
238+
postgresqlJar: $postgresqlJarKey,
239+
jreArchive: $jreArchiveKey
240+
}
241+
}' > "$manifest_path"
242+
243+
aws s3 cp "$manifest_path" "s3://${S3_BUCKET}/${package_key%.zip}.manifest.json" \
244+
--content-type application/json \
245+
--only-show-errors
246+
aws s3 cp "$checksum_path" "s3://${S3_BUCKET}/${package_key%.zip}.sha256" \
247+
--content-type text/plain \
248+
--only-show-errors
249+
aws s3 cp "$zip_path" "s3://${S3_BUCKET}/${package_key}" \
250+
--content-type application/zip \
251+
--content-disposition "attachment; filename=supertokens-${CORE_VERSION}-${platform}.zip" \
252+
--only-show-errors
253+
254+
package_keys="$(jq -c --arg platform "$platform" --arg packageKey "$package_key" '. + {($platform): $packageKey}' <<< "$package_keys")"
255+
done
256+
257+
release_manifest="${WORK_DIR}/core-${CORE_VERSION}.json"
258+
jq -n \
259+
--arg core "$CORE_VERSION" \
260+
--arg plugin "$POSTGRESQL_VERSION" \
261+
--arg pluginInterface "$PLUGIN_INTERFACE_VERSION" \
262+
--arg jreVersion "$JRE_VERSION" \
263+
--argjson packages "$package_keys" \
264+
'{
265+
core: $core,
266+
plugin: $plugin,
267+
pluginInterface: $pluginInterface,
268+
jreVersion: $jreVersion,
269+
packages: $packages
270+
}' > "$release_manifest"
271+
272+
if [[ "$(object_state "$release_manifest_key")" == "exists" ]]; then
273+
remote_release_manifest="${WORK_DIR}/remote-core-${CORE_VERSION}.json"
274+
download_object "$release_manifest_key" "$remote_release_manifest"
275+
existing_release_tuple="$(jq -r '[.core, .plugin, .pluginInterface] | join("/")' "$remote_release_manifest")"
276+
requested_release_tuple="${CORE_VERSION}/${POSTGRESQL_VERSION}/${PLUGIN_INTERFACE_VERSION}"
277+
if [[ "$existing_release_tuple" != "$requested_release_tuple" ]]; then
278+
echo "Refusing to replace ${release_manifest_key} with a different release tuple" >&2
279+
exit 1
280+
fi
281+
fi
282+
283+
aws s3 cp "$release_manifest" \
284+
"s3://${S3_BUCKET}/${release_manifest_key}" \
285+
--content-type application/json \
286+
--only-show-errors
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#!/usr/bin/env bash
2+
3+
set -Eeuo pipefail
4+
5+
required_variables=(CORE_VERSION CORE_DIR PLUGIN_INTERFACE_DIR POSTGRESQL_DIR GITHUB_OUTPUT)
6+
for variable in "${required_variables[@]}"; do
7+
if [[ -z "${!variable:-}" ]]; then
8+
echo "Missing required environment variable: ${variable}" >&2
9+
exit 1
10+
fi
11+
done
12+
13+
plugin_interface_minor="$(
14+
git -C "$CORE_DIR" show "v${CORE_VERSION}:pluginInterfaceSupported.json" \
15+
| jq -r '.versions[0]'
16+
)"
17+
if [[ -z "$plugin_interface_minor" || "$plugin_interface_minor" == "null" ]]; then
18+
echo "Cannot determine plugin-interface version for core v${CORE_VERSION}" >&2
19+
exit 1
20+
fi
21+
22+
plugin_interface_version="${INPUT_PLUGIN_INTERFACE_VERSION:-}"
23+
if [[ -z "$plugin_interface_version" ]]; then
24+
plugin_interface_version="$(
25+
git -C "$PLUGIN_INTERFACE_DIR" tag \
26+
| grep -E "^v${plugin_interface_minor}\.[0-9]+$" \
27+
| sed 's/^v//' \
28+
| sort -V \
29+
| tail -1
30+
)"
31+
fi
32+
if [[ ! "$plugin_interface_version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] ||
33+
[[ "${plugin_interface_version%.*}" != "$plugin_interface_minor" ]]; then
34+
echo "Plugin-interface version must be a stable ${plugin_interface_minor}.x release" >&2
35+
exit 1
36+
fi
37+
git -C "$PLUGIN_INTERFACE_DIR" rev-parse --verify "v${plugin_interface_version}^{commit}" >/dev/null
38+
39+
postgresql_version="${INPUT_POSTGRESQL_VERSION:-}"
40+
if [[ -z "$postgresql_version" ]]; then
41+
while IFS= read -r postgresql_tag; do
42+
supported_minor="$(
43+
git -C "$POSTGRESQL_DIR" show "${postgresql_tag}:pluginInterfaceSupported.json" 2>/dev/null \
44+
| jq -r '.versions[0]' 2>/dev/null || true
45+
)"
46+
if [[ "$supported_minor" == "$plugin_interface_minor" ]]; then
47+
postgresql_version="${postgresql_tag#v}"
48+
break
49+
fi
50+
done < <(git -C "$POSTGRESQL_DIR" tag --sort=-version:refname | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$')
51+
fi
52+
if [[ ! "$postgresql_version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
53+
echo "PostgreSQL plugin version must be a stable X.Y.Z release" >&2
54+
exit 1
55+
fi
56+
57+
postgresql_plugin_interface_minor="$(
58+
git -C "$POSTGRESQL_DIR" show "v${postgresql_version}:pluginInterfaceSupported.json" \
59+
| jq -r '.versions[0]'
60+
)"
61+
if [[ "$postgresql_plugin_interface_minor" != "$plugin_interface_minor" ]]; then
62+
echo "PostgreSQL plugin ${postgresql_version} supports plugin-interface ${postgresql_plugin_interface_minor}, expected ${plugin_interface_minor}" >&2
63+
exit 1
64+
fi
65+
66+
echo "Plugin-interface minor: ${plugin_interface_minor}"
67+
echo "Plugin-interface version: ${plugin_interface_version}"
68+
echo "PostgreSQL plugin version: ${postgresql_version}"
69+
echo "pi_version=${plugin_interface_version}" >> "$GITHUB_OUTPUT"
70+
echo "pg_version=${postgresql_version}" >> "$GITHUB_OUTPUT"
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#!/usr/bin/env bash
2+
3+
set -Eeuo pipefail
4+
5+
if [[ -z "${GITHUB_OUTPUT:-}" ]]; then
6+
echo "GITHUB_OUTPUT is required" >&2
7+
exit 1
8+
fi
9+
10+
versions="$(
11+
printf '%s' "${CORE_VERSIONS:-}" \
12+
| tr ',\n' '\n\n' \
13+
| sed 's/[[:space:]]//g' \
14+
| jq -R 'select(length > 0)' \
15+
| jq -sc .
16+
)"
17+
18+
if [[ "$versions" == "[]" ]]; then
19+
echo "No versions parsed from input" >&2
20+
exit 1
21+
fi
22+
if [[ "$(jq '[.[] | test("^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)$")] | all' <<< "$versions")" != "true" ]]; then
23+
echo "Every version must use X.Y.Z format" >&2
24+
exit 1
25+
fi
26+
if (( $(jq length <<< "$versions") > 256 )); then
27+
echo "A batch cannot contain more than 256 versions" >&2
28+
exit 1
29+
fi
30+
31+
echo "Versions to process: ${versions}"
32+
echo "matrix={\"version\":${versions}}" >> "$GITHUB_OUTPUT"

0 commit comments

Comments
 (0)