1515# DATA_DIR - Data directory (default: /var/lib/hypeman on Linux, ~/Library/Application Support/hypeman on macOS)
1616# CONFIG_DIR - Config directory (default: /etc/hypeman on Linux, ~/.config/hypeman on macOS)
1717#
18+ # On macOS, when no prebuilt server artifact exists for the selected release,
19+ # the installer falls back to building that release from source.
20+ #
1821
1922set -e
2023
@@ -67,6 +70,67 @@ find_release_with_artifact() {
6770 return 1
6871}
6972
73+ find_latest_release_tag () {
74+ local repo=" $1 "
75+
76+ curl -fsSL " https://api.github.com/repos/${repo} /releases/latest" 2> /dev/null | grep ' "tag_name"' | head -1 | cut -d' "' -f4
77+ }
78+
79+ require_source_build_tools () {
80+ command -v git > /dev/null 2>&1 || error " git is required to build from source but not installed"
81+ command -v go > /dev/null 2>&1 || error " go is required to build from source but not installed"
82+ command -v make > /dev/null 2>&1 || error " make is required to build from source but not installed"
83+ }
84+
85+ build_server_from_source () {
86+ local source_ref=" $1 "
87+ local build_dir=" ${TMP_DIR} /hypeman"
88+ local build_log=" ${TMP_DIR} /build.log"
89+
90+ require_source_build_tools
91+
92+ info " Building server from source (ref: ${source_ref} )..."
93+ : > " $build_log "
94+
95+ if ! git clone --branch " $source_ref " --depth 1 -q " https://github.com/${REPO} .git" " $build_dir " >> " $build_log " 2>&1 ; then
96+ error " Failed to clone repository. Build log:\n$( cat " $build_log " ) "
97+ fi
98+
99+ info " Building binaries (this may take a few minutes)..."
100+ if [ " $OS " = " darwin" ]; then
101+ if ! (cd " $build_dir " && make sign-darwin >> " $build_log " 2>&1 ); then
102+ echo " "
103+ echo -e " ${RED} Build/signing failed. Full build log:${NC} "
104+ cat " $build_log "
105+ error " Build/signing failed"
106+ fi
107+ cp " ${build_dir} /config.example.darwin.yaml" " ${TMP_DIR} /config.example.darwin.yaml"
108+ else
109+ if ! (cd " $build_dir " && make build >> " $build_log " 2>&1 ); then
110+ echo " "
111+ echo -e " ${RED} Build failed. Full build log:${NC} "
112+ cat " $build_log "
113+ error " Build failed"
114+ fi
115+ cp " ${build_dir} /config.example.yaml" " ${TMP_DIR} /config.example.yaml"
116+ fi
117+
118+ cp " ${build_dir} /bin/hypeman" " ${TMP_DIR} /${BINARY_NAME} "
119+ if [ " $OS " = " linux" ]; then
120+ cp " ${build_dir} /bin/${UFFD_PAGER_BINARY_NAME} " " ${TMP_DIR} /${UFFD_PAGER_BINARY_NAME} "
121+ fi
122+
123+ if ! (cd " $build_dir " && go build -o " ${TMP_DIR} /hypeman-token" ./cmd/gen-jwt >> " $build_log " 2>&1 ); then
124+ echo " "
125+ echo -e " ${RED} Build failed. Full build log:${NC} "
126+ cat " $build_log "
127+ error " Failed to build hypeman-token"
128+ fi
129+
130+ VERSION=" ${source_ref} (source)"
131+ info " Build complete"
132+ }
133+
70134# =============================================================================
71135# Detect OS and architecture (before pre-flight checks)
72136# =============================================================================
@@ -119,7 +183,6 @@ if [ "$OS" = "darwin" ]; then
119183 error " Intel Macs not supported"
120184 fi
121185 command -v codesign > /dev/null 2>&1 || error " codesign is required but not installed (install Xcode Command Line Tools)"
122- command -v docker > /dev/null 2>&1 || error " Docker CLI is required but not found. Install Docker via Colima or Docker Desktop."
123186 # Check if we need sudo for INSTALL_DIR
124187 if [ ! -w " $INSTALL_DIR " ] 2> /dev/null && [ ! -w " $( dirname " $INSTALL_DIR " ) " ] 2> /dev/null; then
125188 if command -v sudo > /dev/null 2>&1 ; then
@@ -164,11 +227,13 @@ if [ "$count" -gt 1 ]; then
164227 error " BRANCH, VERSION, and BINARY_DIR are mutually exclusive"
165228fi
166229
230+ if [ " ${VERSION:- } " = " latest" ]; then
231+ VERSION=" "
232+ fi
233+
167234# Additional checks for build-from-source mode
168235if [ -n " $BRANCH " ]; then
169- command -v git > /dev/null 2>&1 || error " git is required for BRANCH mode but not installed"
170- command -v go > /dev/null 2>&1 || error " go is required for BRANCH mode but not installed"
171- command -v make > /dev/null 2>&1 || error " make is required for BRANCH mode but not installed"
236+ require_source_build_tools
172237fi
173238
174239# Additional checks for BINARY_DIR mode
@@ -276,83 +341,39 @@ if [ -n "$BINARY_DIR" ]; then
276341
277342 VERSION=" custom (from binary)"
278343elif [ -n " $BRANCH " ]; then
279- # Build from source mode
280- info " Building from source (branch: $BRANCH )..."
281-
282- BUILD_DIR=" ${TMP_DIR} /hypeman"
283- BUILD_LOG=" ${TMP_DIR} /build.log"
284-
285- # Clone repo (quiet)
286- if ! git clone --branch " $BRANCH " --depth 1 -q " https://github.com/${REPO} .git" " $BUILD_DIR " 2>&1 | tee -a " $BUILD_LOG " ; then
287- error " Failed to clone repository. Build log:\n$( cat " $BUILD_LOG " ) "
288- fi
289-
290- info " Building binaries (this may take a few minutes)..."
291- cd " $BUILD_DIR "
292-
293- if ! make build >> " $BUILD_LOG " 2>&1 ; then
294- echo " "
295- echo -e " ${RED} Build failed. Full build log:${NC} "
296- cat " $BUILD_LOG "
297- error " Build failed"
298- fi
299- if [ " $OS " = " darwin" ]; then
300- if ! make sign-darwin >> " $BUILD_LOG " 2>&1 ; then
301- echo " "
302- echo -e " ${RED} Signing failed. Full build log:${NC} "
303- cat " $BUILD_LOG "
304- error " Signing failed"
305- fi
306- cp " config.example.darwin.yaml" " ${TMP_DIR} /config.example.darwin.yaml"
307- else
308- cp " config.example.yaml" " ${TMP_DIR} /config.example.yaml"
309- fi
310- cp " bin/hypeman" " ${TMP_DIR} /${BINARY_NAME} "
311- if [ " $OS " = " linux" ]; then
312- cp " bin/${UFFD_PAGER_BINARY_NAME} " " ${TMP_DIR} /${UFFD_PAGER_BINARY_NAME} "
313- fi
314-
315- # Build hypeman-token (not included in make build)
316- if ! go build -o " ${TMP_DIR} /hypeman-token" ./cmd/gen-jwt >> " $BUILD_LOG " 2>&1 ; then
317- echo " "
318- echo -e " ${RED} Build failed. Full build log:${NC} "
319- cat " $BUILD_LOG "
320- error " Failed to build hypeman-token"
321- fi
322-
323- VERSION=" $BRANCH (source)"
324- cd - > /dev/null
325-
326- info " Build complete"
344+ build_server_from_source " $BRANCH "
327345else
328346 # Download release mode
329347 if [ -z " $VERSION " ]; then
330- info " Fetching latest version with available artifacts..."
331- VERSION=$( find_release_with_artifact " $REPO " " hypeman" " $OS " " $ARCH " )
332- if [ -z " $VERSION " ]; then
333- error " Failed to find a release with artifacts for ${OS} /${ARCH} "
348+ if [ " $OS " = " darwin" ]; then
349+ info " Fetching latest release..."
350+ VERSION=$( find_latest_release_tag " $REPO " || true)
351+ [ -n " $VERSION " ] || error " Failed to find the latest release"
352+ else
353+ info " Fetching latest version with available artifacts..."
354+ VERSION=$( find_release_with_artifact " $REPO " " hypeman" " $OS " " $ARCH " )
355+ [ -n " $VERSION " ] || error " Failed to find a release with artifacts for ${OS} /${ARCH} "
334356 fi
335357 fi
336- info " Installing version: $VERSION "
337358
338- # Construct download URL
339- VERSION_NUM=" ${VERSION# v} "
340- ARCHIVE_NAME=" hypeman_${VERSION_NUM} _${OS} _${ARCH} .tar.gz"
341- DOWNLOAD_URL=" https://github.com/${REPO} /releases/download/${VERSION} /${ARCHIVE_NAME} "
359+ if [ ! -f " ${TMP_DIR} /${BINARY_NAME} " ]; then
360+ info " Installing version: $VERSION "
342361
343- info " Downloading ${ARCHIVE_NAME} ... "
344- if ! curl -fsSL " $DOWNLOAD_URL " -o " ${TMP_DIR} / ${ARCHIVE_NAME} " ; then
345- error " Failed to download from ${DOWNLOAD_URL} "
346- fi
362+ # Construct download URL
363+ VERSION_NUM= " ${VERSION # v} "
364+ ARCHIVE_NAME= " hypeman_ ${VERSION_NUM} _ ${OS} _ ${ARCH} .tar.gz "
365+ DOWNLOAD_URL= " https://github.com/ ${REPO} /releases/download/ ${VERSION} / ${ARCHIVE_NAME} "
347366
348- info " Extracting..."
349- tar -xzf " ${TMP_DIR} /${ARCHIVE_NAME} " -C " $TMP_DIR "
367+ info " Downloading ${ARCHIVE_NAME} ..."
368+ if curl -fsSL " $DOWNLOAD_URL " -o " ${TMP_DIR} /${ARCHIVE_NAME} " ; then
369+ info " Extracting..."
370+ tar -xzf " ${TMP_DIR} /${ARCHIVE_NAME} " -C " $TMP_DIR "
350371
351- # On macOS, codesign after extraction with virtualization entitlements
352- if [ " $OS " = " darwin" ]; then
353- info " Signing binaries..."
354- ENTITLEMENTS_TMP=" ${TMP_DIR} /vz.entitlements"
355- cat > " $ENTITLEMENTS_TMP " << 'ENTITLEMENTS '
372+ # On macOS, codesign after extraction with virtualization entitlements
373+ if [ " $OS " = " darwin" ]; then
374+ info " Signing binaries..."
375+ ENTITLEMENTS_TMP=" ${TMP_DIR} /vz.entitlements"
376+ cat > " $ENTITLEMENTS_TMP " << 'ENTITLEMENTS '
356377<?xml version="1.0" encoding="UTF-8"?>
357378<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
358379<plist version="1.0">
@@ -366,10 +387,18 @@ else
366387</dict>
367388</plist>
368389ENTITLEMENTS
369- if ! codesign --force --sign - --entitlements " $ENTITLEMENTS_TMP " " ${TMP_DIR} /${BINARY_NAME} " 2> /dev/null; then
370- warn " codesign failed — vz hypervisor will not work without virtualization entitlement"
390+ if ! codesign --force --sign - --entitlements " $ENTITLEMENTS_TMP " " ${TMP_DIR} /${BINARY_NAME} " 2> /dev/null; then
391+ warn " codesign failed — vz hypervisor will not work without virtualization entitlement"
392+ fi
393+ rm -f " $ENTITLEMENTS_TMP "
394+ fi
395+ elif [ " $OS " = " darwin" ]; then
396+ rm -f " ${TMP_DIR} /${ARCHIVE_NAME} "
397+ warn " Prebuilt macOS server artifact ${ARCHIVE_NAME} could not be downloaded; building ${VERSION} from source instead"
398+ build_server_from_source " $VERSION "
399+ else
400+ error " Failed to download from ${DOWNLOAD_URL} "
371401 fi
372- rm -f " $ENTITLEMENTS_TMP "
373402 fi
374403fi
375404
646675if [ " $OS " = " darwin" ]; then
647676 info " Attempting to build builder image..."
648677 if command -v docker > /dev/null 2>&1 ; then
649- if [ -n " $BRANCH " ] && [ - d " ${TMP_DIR} /hypeman" ]; then
678+ if [ -d " ${TMP_DIR} /hypeman" ]; then
650679 BUILD_CONTEXT=" ${TMP_DIR} /hypeman"
651680 else
652681 BUILD_CONTEXT=" "
0 commit comments