mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-02-18 00:17:39 +01:00
361 lines
13 KiB
Bash
Executable File
361 lines
13 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
# Build script for Pulse releases
|
|
# Creates release archives for different architectures
|
|
|
|
set -euo pipefail
|
|
|
|
# Use Go 1.24 if available
|
|
if [ -x /usr/local/go/bin/go ]; then
|
|
export PATH=/usr/local/go/bin:$PATH
|
|
fi
|
|
|
|
# Force static binaries so release artifacts run on older glibc hosts
|
|
export CGO_ENABLED=0
|
|
|
|
VERSION=${1:-$(cat VERSION)}
|
|
BUILD_DIR="build"
|
|
RELEASE_DIR="release"
|
|
|
|
echo "Building Pulse v${VERSION}..."
|
|
|
|
# Clean previous builds
|
|
rm -rf $BUILD_DIR $RELEASE_DIR
|
|
mkdir -p $BUILD_DIR $RELEASE_DIR
|
|
|
|
# Build frontend
|
|
echo "Building frontend..."
|
|
npm --prefix frontend-modern ci
|
|
npm --prefix frontend-modern run build
|
|
|
|
# Copy frontend dist for embedding (required for Go embed)
|
|
echo "Copying frontend dist for embedding..."
|
|
rm -rf internal/api/frontend-modern
|
|
mkdir -p internal/api/frontend-modern
|
|
cp -r frontend-modern/dist internal/api/frontend-modern/
|
|
|
|
# Build for different architectures
|
|
declare -A builds=(
|
|
["linux-amd64"]="GOOS=linux GOARCH=amd64"
|
|
["linux-arm64"]="GOOS=linux GOARCH=arm64"
|
|
["linux-armv7"]="GOOS=linux GOARCH=arm GOARM=7"
|
|
["linux-armv6"]="GOOS=linux GOARCH=arm GOARM=6"
|
|
["linux-386"]="GOOS=linux GOARCH=386"
|
|
)
|
|
|
|
for build_name in "${!builds[@]}"; do
|
|
echo "Building for $build_name..."
|
|
|
|
# Get build environment
|
|
build_env="${builds[$build_name]}"
|
|
|
|
build_time=$(date -u '+%Y-%m-%d_%H:%M:%S')
|
|
git_commit=$(git rev-parse --short HEAD 2>/dev/null || echo 'unknown')
|
|
|
|
# Build backend binary with version info
|
|
env $build_env go build \
|
|
-ldflags="-s -w -X main.Version=v${VERSION} -X main.BuildTime=${build_time} -X main.GitCommit=${git_commit} -X github.com/rcourtman/pulse-go-rewrite/internal/dockeragent.Version=v${VERSION}" \
|
|
-trimpath \
|
|
-o "$BUILD_DIR/pulse-$build_name" \
|
|
./cmd/pulse
|
|
|
|
# Build docker agent binary
|
|
env $build_env go build \
|
|
-ldflags="-s -w -X github.com/rcourtman/pulse-go-rewrite/internal/dockeragent.Version=v${VERSION}" \
|
|
-trimpath \
|
|
-o "$BUILD_DIR/pulse-docker-agent-$build_name" \
|
|
./cmd/pulse-docker-agent
|
|
|
|
# Build host agent binary
|
|
env $build_env go build \
|
|
-ldflags="-s -w -X github.com/rcourtman/pulse-go-rewrite/internal/hostagent.Version=v${VERSION}" \
|
|
-trimpath \
|
|
-o "$BUILD_DIR/pulse-host-agent-$build_name" \
|
|
./cmd/pulse-host-agent
|
|
|
|
# Build temperature proxy binary
|
|
env $build_env go build \
|
|
-ldflags="-s -w -X main.Version=v${VERSION} -X main.BuildTime=${build_time} -X main.GitCommit=${git_commit}" \
|
|
-trimpath \
|
|
-o "$BUILD_DIR/pulse-sensor-proxy-$build_name" \
|
|
./cmd/pulse-sensor-proxy
|
|
|
|
# Create release archive with proper structure
|
|
tar_name="pulse-v${VERSION}-${build_name}.tar.gz"
|
|
|
|
# Create staging directory
|
|
staging_dir="$BUILD_DIR/staging-$build_name"
|
|
rm -rf "$staging_dir"
|
|
mkdir -p "$staging_dir/bin"
|
|
mkdir -p "$staging_dir/scripts"
|
|
|
|
# Copy binaries and VERSION file
|
|
cp "$BUILD_DIR/pulse-$build_name" "$staging_dir/bin/pulse"
|
|
cp "$BUILD_DIR/pulse-docker-agent-$build_name" "$staging_dir/bin/pulse-docker-agent"
|
|
cp "$BUILD_DIR/pulse-host-agent-$build_name" "$staging_dir/bin/pulse-host-agent"
|
|
cp "$BUILD_DIR/pulse-sensor-proxy-$build_name" "$staging_dir/bin/pulse-sensor-proxy"
|
|
cp "scripts/install-docker-agent.sh" "$staging_dir/scripts/install-docker-agent.sh"
|
|
cp "scripts/install-container-agent.sh" "$staging_dir/scripts/install-container-agent.sh"
|
|
cp "scripts/install-host-agent.sh" "$staging_dir/scripts/install-host-agent.sh"
|
|
cp "scripts/install-host-agent.ps1" "$staging_dir/scripts/install-host-agent.ps1"
|
|
cp "scripts/uninstall-host-agent.sh" "$staging_dir/scripts/uninstall-host-agent.sh"
|
|
cp "scripts/uninstall-host-agent.ps1" "$staging_dir/scripts/uninstall-host-agent.ps1"
|
|
cp "scripts/install-sensor-proxy.sh" "$staging_dir/scripts/install-sensor-proxy.sh"
|
|
cp "scripts/install-docker.sh" "$staging_dir/scripts/install-docker.sh"
|
|
chmod 755 "$staging_dir/scripts/"*.sh "$staging_dir/scripts/"*.ps1
|
|
echo "$VERSION" > "$staging_dir/VERSION"
|
|
|
|
# Create tarball from staging directory
|
|
cd "$staging_dir"
|
|
tar -czf "../../$RELEASE_DIR/$tar_name" .
|
|
cd ../..
|
|
|
|
# Cleanup staging
|
|
rm -rf "$staging_dir"
|
|
|
|
echo "Created $RELEASE_DIR/$tar_name"
|
|
done
|
|
|
|
# Create universal tarball with all binaries
|
|
echo "Creating universal tarball..."
|
|
universal_dir="$BUILD_DIR/universal"
|
|
rm -rf "$universal_dir"
|
|
mkdir -p "$universal_dir/bin"
|
|
mkdir -p "$universal_dir/scripts"
|
|
|
|
# Copy all binaries to bin/ directory to maintain consistent structure
|
|
for build_name in "${!builds[@]}"; do
|
|
cp "$BUILD_DIR/pulse-$build_name" "$universal_dir/bin/pulse-${build_name}"
|
|
cp "$BUILD_DIR/pulse-docker-agent-$build_name" "$universal_dir/bin/pulse-docker-agent-${build_name}"
|
|
cp "$BUILD_DIR/pulse-host-agent-$build_name" "$universal_dir/bin/pulse-host-agent-${build_name}"
|
|
cp "$BUILD_DIR/pulse-sensor-proxy-$build_name" "$universal_dir/bin/pulse-sensor-proxy-${build_name}"
|
|
done
|
|
|
|
cp "scripts/install-docker-agent.sh" "$universal_dir/scripts/install-docker-agent.sh"
|
|
cp "scripts/install-container-agent.sh" "$universal_dir/scripts/install-container-agent.sh"
|
|
cp "scripts/install-host-agent.sh" "$universal_dir/scripts/install-host-agent.sh"
|
|
cp "scripts/install-host-agent.ps1" "$universal_dir/scripts/install-host-agent.ps1"
|
|
cp "scripts/uninstall-host-agent.sh" "$universal_dir/scripts/uninstall-host-agent.sh"
|
|
cp "scripts/uninstall-host-agent.ps1" "$universal_dir/scripts/uninstall-host-agent.ps1"
|
|
cp "scripts/install-sensor-proxy.sh" "$universal_dir/scripts/install-sensor-proxy.sh"
|
|
cp "scripts/install-docker.sh" "$universal_dir/scripts/install-docker.sh"
|
|
chmod 755 "$universal_dir/scripts/"*.sh "$universal_dir/scripts/"*.ps1
|
|
|
|
# Create a detection script that creates the pulse symlink based on architecture
|
|
cat > "$universal_dir/bin/pulse" << 'EOF'
|
|
#!/bin/sh
|
|
# Auto-detect architecture and run appropriate binary
|
|
|
|
ARCH=$(uname -m)
|
|
case "$ARCH" in
|
|
x86_64|amd64)
|
|
exec "$(dirname "$0")/pulse-linux-amd64" "$@"
|
|
;;
|
|
aarch64|arm64)
|
|
exec "$(dirname "$0")/pulse-linux-arm64" "$@"
|
|
;;
|
|
armv7l|armhf)
|
|
exec "$(dirname "$0")/pulse-linux-armv7" "$@"
|
|
;;
|
|
*)
|
|
echo "Unsupported architecture: $ARCH" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
EOF
|
|
chmod +x "$universal_dir/bin/pulse"
|
|
|
|
cat > "$universal_dir/bin/pulse-docker-agent" << 'EOF'
|
|
#!/bin/sh
|
|
# Auto-detect architecture and run appropriate pulse-docker-agent binary
|
|
|
|
ARCH=$(uname -m)
|
|
case "$ARCH" in
|
|
x86_64|amd64)
|
|
exec "$(dirname "$0")/pulse-docker-agent-linux-amd64" "$@"
|
|
;;
|
|
aarch64|arm64)
|
|
exec "$(dirname "$0")/pulse-docker-agent-linux-arm64" "$@"
|
|
;;
|
|
armv7l|armhf)
|
|
exec "$(dirname "$0")/pulse-docker-agent-linux-armv7" "$@"
|
|
;;
|
|
*)
|
|
echo "Unsupported architecture: $ARCH" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
EOF
|
|
chmod +x "$universal_dir/bin/pulse-docker-agent"
|
|
|
|
cat > "$universal_dir/bin/pulse-sensor-proxy" << 'EOF'
|
|
#!/bin/sh
|
|
# Auto-detect architecture and run appropriate pulse-sensor-proxy binary
|
|
|
|
ARCH=$(uname -m)
|
|
case "$ARCH" in
|
|
x86_64|amd64)
|
|
exec "$(dirname "$0")/pulse-sensor-proxy-linux-amd64" "$@"
|
|
;;
|
|
aarch64|arm64)
|
|
exec "$(dirname "$0")/pulse-sensor-proxy-linux-arm64" "$@"
|
|
;;
|
|
armv7l|armhf)
|
|
exec "$(dirname "$0")/pulse-sensor-proxy-linux-armv7" "$@"
|
|
;;
|
|
*)
|
|
echo "Unsupported architecture: $ARCH" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
EOF
|
|
chmod +x "$universal_dir/bin/pulse-sensor-proxy"
|
|
|
|
cat > "$universal_dir/bin/pulse-host-agent" << 'EOF'
|
|
#!/bin/sh
|
|
# Auto-detect architecture and run appropriate pulse-host-agent binary
|
|
|
|
ARCH=$(uname -m)
|
|
case "$ARCH" in
|
|
x86_64|amd64)
|
|
exec "$(dirname "$0")/pulse-host-agent-linux-amd64" "$@"
|
|
;;
|
|
aarch64|arm64)
|
|
exec "$(dirname "$0")/pulse-host-agent-linux-arm64" "$@"
|
|
;;
|
|
armv7l|armhf)
|
|
exec "$(dirname "$0")/pulse-host-agent-linux-armv7" "$@"
|
|
;;
|
|
*)
|
|
echo "Unsupported architecture: $ARCH" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
EOF
|
|
chmod +x "$universal_dir/bin/pulse-host-agent"
|
|
|
|
# Add VERSION file
|
|
echo "$VERSION" > "$universal_dir/VERSION"
|
|
|
|
# Build host agent for macOS
|
|
echo "Building host agent for macOS amd64..."
|
|
env GOOS=darwin GOARCH=amd64 go build \
|
|
-ldflags="-s -w -X github.com/rcourtman/pulse-go-rewrite/internal/hostagent.Version=v${VERSION}" \
|
|
-trimpath \
|
|
-o "$BUILD_DIR/pulse-host-agent-darwin-amd64" \
|
|
./cmd/pulse-host-agent
|
|
|
|
echo "Building host agent for macOS arm64..."
|
|
env GOOS=darwin GOARCH=arm64 go build \
|
|
-ldflags="-s -w -X github.com/rcourtman/pulse-go-rewrite/internal/hostagent.Version=v${VERSION}" \
|
|
-trimpath \
|
|
-o "$BUILD_DIR/pulse-host-agent-darwin-arm64" \
|
|
./cmd/pulse-host-agent
|
|
|
|
# Build host agent for Windows
|
|
echo "Building host agent for Windows amd64..."
|
|
env GOOS=windows GOARCH=amd64 go build \
|
|
-ldflags="-s -w -X github.com/rcourtman/pulse-go-rewrite/internal/hostagent.Version=v${VERSION}" \
|
|
-trimpath \
|
|
-o "$BUILD_DIR/pulse-host-agent-windows-amd64.exe" \
|
|
./cmd/pulse-host-agent
|
|
|
|
echo "Building host agent for Windows arm64..."
|
|
env GOOS=windows GOARCH=arm64 go build \
|
|
-ldflags="-s -w -X github.com/rcourtman/pulse-go-rewrite/internal/hostagent.Version=v${VERSION}" \
|
|
-trimpath \
|
|
-o "$BUILD_DIR/pulse-host-agent-windows-arm64.exe" \
|
|
./cmd/pulse-host-agent
|
|
|
|
echo "Building host agent for Windows 386..."
|
|
env GOOS=windows GOARCH=386 go build \
|
|
-ldflags="-s -w -X github.com/rcourtman/pulse-go-rewrite/internal/hostagent.Version=v${VERSION}" \
|
|
-trimpath \
|
|
-o "$BUILD_DIR/pulse-host-agent-windows-386.exe" \
|
|
./cmd/pulse-host-agent
|
|
|
|
# Package standalone host agent binaries
|
|
tar -czf "$RELEASE_DIR/pulse-host-agent-v${VERSION}-darwin-amd64.tar.gz" -C "$BUILD_DIR" pulse-host-agent-darwin-amd64
|
|
tar -czf "$RELEASE_DIR/pulse-host-agent-v${VERSION}-darwin-arm64.tar.gz" -C "$BUILD_DIR" pulse-host-agent-darwin-arm64
|
|
zip -j "$RELEASE_DIR/pulse-host-agent-v${VERSION}-windows-amd64.zip" "$BUILD_DIR/pulse-host-agent-windows-amd64.exe"
|
|
zip -j "$RELEASE_DIR/pulse-host-agent-v${VERSION}-windows-arm64.zip" "$BUILD_DIR/pulse-host-agent-windows-arm64.exe"
|
|
zip -j "$RELEASE_DIR/pulse-host-agent-v${VERSION}-windows-386.zip" "$BUILD_DIR/pulse-host-agent-windows-386.exe"
|
|
|
|
# Copy Windows and macOS binaries into universal tarball for /download/ endpoint
|
|
echo "Adding Windows and macOS binaries to universal tarball..."
|
|
cp "$BUILD_DIR/pulse-host-agent-darwin-amd64" "$universal_dir/bin/"
|
|
cp "$BUILD_DIR/pulse-host-agent-darwin-arm64" "$universal_dir/bin/"
|
|
cp "$BUILD_DIR/pulse-host-agent-windows-amd64.exe" "$universal_dir/bin/"
|
|
cp "$BUILD_DIR/pulse-host-agent-windows-arm64.exe" "$universal_dir/bin/"
|
|
cp "$BUILD_DIR/pulse-host-agent-windows-386.exe" "$universal_dir/bin/"
|
|
|
|
# Create symlinks for Windows binaries without .exe extension (required for download endpoint)
|
|
ln -s pulse-host-agent-windows-amd64.exe "$universal_dir/bin/pulse-host-agent-windows-amd64"
|
|
ln -s pulse-host-agent-windows-arm64.exe "$universal_dir/bin/pulse-host-agent-windows-arm64"
|
|
ln -s pulse-host-agent-windows-386.exe "$universal_dir/bin/pulse-host-agent-windows-386"
|
|
|
|
# Create universal tarball
|
|
cd "$universal_dir"
|
|
tar -czf "../../$RELEASE_DIR/pulse-v${VERSION}.tar.gz" .
|
|
cd ../..
|
|
|
|
# Cleanup
|
|
rm -rf "$universal_dir"
|
|
|
|
# Optionally package Helm chart
|
|
if [ "${SKIP_HELM_PACKAGE:-0}" != "1" ]; then
|
|
if command -v helm >/dev/null 2>&1; then
|
|
echo "Packaging Helm chart..."
|
|
./scripts/package-helm-chart.sh "$VERSION"
|
|
if [ -f "dist/pulse-$VERSION.tgz" ]; then
|
|
cp "dist/pulse-$VERSION.tgz" "$RELEASE_DIR/"
|
|
fi
|
|
else
|
|
echo "Helm not found on PATH; skipping Helm chart packaging. Install Helm 3.9+ or set SKIP_HELM_PACKAGE=1 to silence this message."
|
|
fi
|
|
fi
|
|
|
|
# Copy install.sh to release directory (required for GitHub releases)
|
|
echo "Copying install.sh to release directory..."
|
|
cp install.sh "$RELEASE_DIR/"
|
|
|
|
# Generate checksums (include tarballs, zip files, helm chart, and install.sh)
|
|
cd "$RELEASE_DIR"
|
|
shopt -s nullglob extglob
|
|
# Match all tarballs, zip files, and install.sh
|
|
checksum_files=( *.tar.gz *.zip install.sh )
|
|
if compgen -G "pulse-*.tgz" > /dev/null; then
|
|
checksum_files+=( pulse-*.tgz )
|
|
fi
|
|
if [ ${#checksum_files[@]} -eq 0 ]; then
|
|
echo "Warning: no release artifacts found to checksum."
|
|
else
|
|
# Generate checksums from a single sha256sum run for deterministic results (prevents #671 checksum mismatches)
|
|
checksum_output="$(sha256sum "${checksum_files[@]}" | sort -k 2)"
|
|
printf '%s\n' "$checksum_output" > checksums.txt
|
|
|
|
# Emit per-file .sha256 artifacts for backward compatibility while legacy installers transition off them
|
|
while read -r checksum filename; do
|
|
printf '%s %s\n' "$checksum" "$filename" > "${filename}.sha256"
|
|
done <<< "$checksum_output"
|
|
|
|
if [ -n "${SIGNING_KEY_ID:-}" ]; then
|
|
if command -v gpg >/dev/null 2>&1; then
|
|
echo "Signing checksums with GPG key ${SIGNING_KEY_ID}..."
|
|
gpg --batch --yes --detach-sign --armor \
|
|
--local-user "${SIGNING_KEY_ID}" \
|
|
--output checksums.txt.asc \
|
|
checksums.txt
|
|
else
|
|
echo "SIGNING_KEY_ID is set but gpg is not installed; skipping signature."
|
|
fi
|
|
fi
|
|
fi
|
|
shopt -u nullglob
|
|
cd ..
|
|
|
|
echo
|
|
echo "Release build complete!"
|
|
echo "Archives created in $RELEASE_DIR/"
|
|
ls -lh $RELEASE_DIR/
|