Skip to content

Commit 7592cb8

Browse files
committed
ci(ace): add native RPM/DEB release pipeline alongside goreleaser + docker
1 parent beecb35 commit 7592cb8

16 files changed

Lines changed: 1776 additions & 60 deletions

File tree

.github/workflows/release.yaml

Lines changed: 1067 additions & 60 deletions
Large diffs are not rendered by default.

common/build.sh

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
# Entry point for the pgEdge builder-action. Invoked as:
5+
# common/build.sh <component>
6+
# where <component> is a packaging dir under the repo root that holds a
7+
# common.sh + build-rpm.sh / build-deb.sh (e.g. "packaging/pg_duckdb").
8+
COMPONENT_NAME=$1
9+
source "$(dirname "$0")/../${COMPONENT_NAME}/common.sh"
10+
11+
# common-functions.sh is a committed copy of the shared pgEdge build helpers
12+
# (from pgedge-enterprise-packages/common/). The builder-action mounts the repo
13+
# and runs this script but does not supply it, so it must live in the repo —
14+
# same pattern as ai-dba-workbench's packaging/scripts/common-functions.sh.
15+
COMMON_FILE="$(dirname "$0")/common-functions.sh"
16+
if [ -f "$COMMON_FILE" ]; then
17+
source "$COMMON_FILE"
18+
else
19+
echo "Error: $COMMON_FILE not found!" >&2
20+
exit 1
21+
fi
22+
23+
###########
24+
# Main
25+
###########
26+
detect_os_type
27+
prepare
28+
build
29+
post_build

common/common-functions.sh

Lines changed: 281 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,281 @@
1+
#!/bin/bash
2+
3+
install_syft(){
4+
5+
# Install syft from its pinned release tarball and verify it against the
6+
# published checksums before installing — avoids piping a remote installer
7+
# script straight into a root shell. Override SYFT_VERSION to bump.
8+
SYFT_VERSION="${SYFT_VERSION:-v1.45.1}"
9+
local ver="${SYFT_VERSION#v}" arch
10+
case "$(uname -m)" in
11+
x86_64) arch=amd64 ;;
12+
aarch64) arch=arm64 ;;
13+
*) echo "unsupported arch for syft: $(uname -m)" >&2; return 1 ;;
14+
esac
15+
local tgz="syft_${ver}_linux_${arch}.tar.gz"
16+
local base="https://github.com/anchore/syft/releases/download/v${ver}"
17+
local tmp; tmp="$(mktemp -d)"
18+
echo "Installing syft ${SYFT_VERSION} (${arch})..."
19+
curl -sSfL "${base}/${tgz}" -o "${tmp}/${tgz}"
20+
curl -sSfL "${base}/syft_${ver}_checksums.txt" -o "${tmp}/checksums.txt"
21+
( cd "${tmp}" && grep " ${tgz}\$" checksums.txt | sha256sum -c - )
22+
tar -xzf "${tmp}/${tgz}" -C "${tmp}" syft
23+
sudo install -m 0755 "${tmp}/syft" /usr/local/bin/syft
24+
rm -rf "${tmp}"
25+
syft version
26+
}
27+
28+
setup_dnf_build_env(){
29+
30+
echo "Installing required packages..."
31+
dnf groupinstall "Development Tools" -y
32+
dnf install -y rpm-build rpmdevtools yum-utils tar wget git gnupg2 sudo
33+
34+
echo "📦 Enabling additional repositories..."
35+
dnf install -y epel-release
36+
if [ "$RHEL" = "8" ]; then
37+
dnf config-manager --set-enabled powertools
38+
else
39+
dnf config-manager --set-enabled crb
40+
fi
41+
42+
echo "Configuring pgEdge repository..."
43+
configure_pgedge_dnf_repo $REPO_TYPE
44+
45+
echo "Setting up RPM build environment..."
46+
rpmdev-setuptree
47+
48+
install_syft
49+
}
50+
51+
setup_apt_build_env(){
52+
53+
echo "Installing build tools and dependencies..."
54+
sudo ln -fs /usr/share/zoneinfo/UTC /etc/localtime
55+
56+
sudo apt-get update
57+
sudo apt-get install -y devscripts build-essential pkg-config fakeroot git curl \
58+
ca-certificates debhelper dpkg-dev gnupg2 wget sudo lsb-release
59+
60+
echo "Configuring pgEdge repository..."
61+
configure_pgedge_apt_repo $REPO_TYPE
62+
63+
install_syft
64+
}
65+
66+
rename_ddeb_packages(){
67+
# Rename any *.ddeb (debug-symbol packages) to *.deb. Uses find -print0 so it
68+
# is safe under `set -euo pipefail` when there are NO .ddeb files (no grep
69+
# non-zero exit) and tolerates filenames with spaces.
70+
local build_dir="$1" f
71+
find "$build_dir" -maxdepth 1 -type f -name '*.ddeb' -print0 | while IFS= read -r -d '' f; do
72+
mv -- "$f" "${f%.ddeb}.deb"
73+
done
74+
}
75+
76+
configure_pgedge_dnf_repo() {
77+
local REPO_TYPE="${1:-daily}" # "daily" or "staging"
78+
79+
sudo dnf install -y https://dnf.pgedge.com/reporpm/pgedge-release-latest.noarch.rpm
80+
sudo sed -i "s|release|$REPO_TYPE|g" /etc/yum.repos.d/pgedge.repo
81+
82+
echo "Repo configured at /etc/yum.repos.d/pgedge.repo"
83+
}
84+
85+
configure_pgedge_apt_repo(){
86+
local REPO_TYPE="${1:-daily}" # "daily" or "staging"
87+
local REPO_PATH="repodeb"
88+
89+
curl -sSL https://apt.pgedge.com/${REPO_PATH}/pgedge-release_latest_all.deb -o /tmp/pgedge-release.deb && sudo dpkg -i /tmp/pgedge-release.deb && rm -f /tmp/pgedge-release.deb || true
90+
sed -i "s|release|$REPO_TYPE|g" /etc/apt/sources.list.d/pgedge.sources
91+
apt-get update
92+
93+
echo "Repo configured at /etc/apt/sources.list.d/pgedge.sources"
94+
}
95+
96+
detect_os_type(){
97+
if command -v dnf &>/dev/null || command -v yum &>/dev/null; then
98+
echo "Detected RPM-based system"
99+
source "$(dirname "$0")/../${COMPONENT_NAME}/build-rpm.sh"
100+
elif command -v apt-get &>/dev/null; then
101+
echo "Detected Debian-based system"
102+
source "$(dirname "$0")/../${COMPONENT_NAME}/build-deb.sh"
103+
else
104+
echo "Unsupported platform: No known package manager found" >&2
105+
exit 1
106+
fi
107+
}
108+
109+
import_gpg_keys() {
110+
if ! command -v rpm &>/dev/null || ! command -v gpg &>/dev/null; then
111+
echo "Installing rpm or gpg"
112+
if command -v dnf &>/dev/null; then
113+
sudo dnf install -y rpm gnupg2
114+
elif command -v apt-get &>/dev/null; then
115+
sudo apt-get install -y rpm gnupg2
116+
fi
117+
if [ $? -ne 0 ]; then
118+
echo "Error: Failed to install rpm or gnupg2"
119+
return 1
120+
fi
121+
fi
122+
123+
PRI_FILE=$(dirname "$0")/public.key
124+
PUB_FILE=$(dirname "$0")/private.key
125+
126+
GPG_PUBLIC_KEY=$(cat $PRI_FILE)
127+
GPG_PRIVATE_KEY=$(cat $PUB_FILE)
128+
rm -f $PRI_FILE $PUB_FILE
129+
130+
[ -z "$GPG_PUBLIC_KEY" ] && { echo "Error: GPG_PUBLIC_KEY is unset"; return 1; }
131+
[ -z "$GPG_PRIVATE_KEY" ] && { echo "Error: GPG_PRIVATE_KEY is unset"; return 1; }
132+
133+
PUBLIC_KEY_FILE=$(mktemp)
134+
echo "$GPG_PUBLIC_KEY" > "$PUBLIC_KEY_FILE"
135+
136+
gpg --import "$PUBLIC_KEY_FILE" || {
137+
echo "Error: Failed to import public key"
138+
rm -f "$PUBLIC_KEY_FILE"
139+
return 1
140+
}
141+
142+
rpm --import "$PUBLIC_KEY_FILE" || {
143+
echo "Error: Failed to import public key to RPM"
144+
rm -f "$PUBLIC_KEY_FILE"
145+
return 1
146+
}
147+
148+
PRIVATE_KEY_FILE=$(mktemp)
149+
echo "$GPG_PRIVATE_KEY" > "$PRIVATE_KEY_FILE"
150+
gpg --import "$PRIVATE_KEY_FILE" || {
151+
echo "Error: Failed to import private key"
152+
rm -f "$PRIVATE_KEY_FILE"
153+
rm -f "$PUBLIC_KEY_FILE"
154+
return 1
155+
}
156+
rm -f "$PRIVATE_KEY_FILE"
157+
rm -f "$PUBLIC_KEY_FILE"
158+
return 0
159+
}
160+
161+
sign_rpms() {
162+
# Check if at least one file is provided
163+
if [ $# -eq 0 ]; then
164+
echo "Error: No files provided to sign."
165+
return 1
166+
fi
167+
168+
# Check if rpmsign and gpg are installed, install if not
169+
if ! command -v rpmsign &>/dev/null; then
170+
echo "rpmsign not found. Installing rpm-sign"
171+
if command -v sudo &>/dev/null; then
172+
sudo dnf install -y rpm-sign
173+
else
174+
dnf install -y rpm-sign
175+
fi
176+
if [ $? -ne 0 ]; then
177+
echo "Error: Failed to install rpm-sign"
178+
return 1
179+
fi
180+
fi
181+
182+
# Get the key ID of the imported private key
183+
KEY_ID=$(gpg --list-secret-keys --with-colons | awk -F: '/^sec/{print $5}' | head -n 1)
184+
if [ -z "$KEY_ID" ]; then
185+
echo "Error: No private key found after import."
186+
rm -f "$PRIVATE_KEY_FILE"
187+
rm -rf "$GNUPGHOME"
188+
return 1
189+
fi
190+
191+
echo "=======================Signing RPMs======================="
192+
# Sign each RPM file
193+
for file in "$@"; do
194+
# Ensure the file has /output/ prefix if relative
195+
if [[ ! "$file" = /* ]]; then
196+
file="/output/$file"
197+
fi
198+
199+
if [ ! -f "$file" ]; then
200+
echo "Error: File '$file' does not exist."
201+
continue
202+
fi
203+
204+
# Check if the file is an RPM
205+
if ! file "$file" | grep -q "RPM"; then
206+
echo "Error: File '$file' is not an RPM file."
207+
continue
208+
fi
209+
210+
# Sign the RPM using rpmsign, using passphrase if provided
211+
rpmsign --define "_gpg_name $KEY_ID" --addsign "$file" >/dev/null 2>&1
212+
213+
if [ $? -eq 0 ]; then
214+
echo "Successfully signed '$file'."
215+
else
216+
echo "Error: Failed to sign '$file'."
217+
fi
218+
done
219+
echo "=======================Signing Completes=================="
220+
221+
# Clean up
222+
rm -f "$PRIVATE_KEY_FILE"
223+
}
224+
225+
validate_signatures() {
226+
227+
# Check if files are provided
228+
if [ $# -eq 0 ]; then
229+
echo "Error: No files provided to validate."
230+
return 1
231+
fi
232+
233+
# Install dependencies
234+
if ! command -v rpm &>/dev/null; then
235+
echo "Installing rpm"
236+
if command -v sudo &>/dev/null; then
237+
sudo dnf install -y rpm
238+
else
239+
dnf install -y rpm
240+
fi
241+
if [ $? -ne 0 ]; then
242+
echo "Error: Failed to install rpm"
243+
return 1
244+
fi
245+
fi
246+
247+
# Validate each RPM
248+
local all_valid=0
249+
echo "=======================Starting validation======================="
250+
for file in "$@"; do
251+
if [[ ! "$file" = /* ]]; then
252+
file="/output/$file"
253+
fi
254+
255+
if [ ! -f "$file" ]; then
256+
echo "Error: File '$file' does not exist."
257+
all_valid=1
258+
continue
259+
fi
260+
261+
if ! file "$file" | grep -q "RPM"; then
262+
echo "Error: File '$file' is not an RPM file."
263+
all_valid=1
264+
continue
265+
fi
266+
267+
CHECKSIG_OUTPUT=$(rpm --checksig "$file" 2>&1)
268+
echo "$CHECKSIG_OUTPUT"
269+
if echo "$CHECKSIG_OUTPUT" | grep -q "digests signatures OK"; then
270+
echo "Signature for '$file' is valid."
271+
else
272+
echo "Error: Signature for '$file' is invalid or missing."
273+
all_valid=1
274+
fi
275+
done
276+
echo "=======================Validation completes======================"
277+
# Clean up
278+
rm -f "$PUBLIC_KEY_FILE"
279+
280+
return $all_valid
281+
}

0 commit comments

Comments
 (0)