From 592ff9c0cf5b2deb27ff19fd2acf990870646dbd Mon Sep 17 00:00:00 2001 From: Corey Ryan Dean Date: Sat, 16 May 2026 09:05:54 -0500 Subject: [PATCH] fix(release): reject unsupported Unix packaging --- .github/workflows/ci.yml | 3 ++ ReadMe.md | 2 + publish.sh | 85 ++++++++++++++++++++++---------- scripts/test_publish_contract.sh | 56 +++++++++++++++++++++ 4 files changed, 119 insertions(+), 27 deletions(-) create mode 100644 scripts/test_publish_contract.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 246b546..1146a26 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -51,6 +51,9 @@ jobs: - name: Check out repository uses: actions/checkout@v4 + - name: Validate publish contract + run: bash scripts/test_publish_contract.sh + - name: Install build dependencies run: brew install cmake ninja diff --git a/ReadMe.md b/ReadMe.md index f8d750c..516041e 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -143,6 +143,8 @@ cd blitz-forge Build artifacts land in [`bin/`](bin), a staged [`release/`](release) directory, and a redistributable ZIP archive such as `release/blitzforge-macos-arm64.zip` or `release/blitzforge-windows-x64.zip`. +`./publish.sh` is currently a macOS release-packaging path. Linux and other Unix hosts can build `blitzcc` from source with `./compile.sh`, but they do not yet produce the runtime/linker release bundle that BlitzForge archives ship. + The compiler accepts an explicit `-target` flag (`host`, `windows-x86`, or `macos-arm64`). On macOS hosts, `host` and `macos-arm64` are equivalent; cross-compiling to a foreign target is rejected up-front rather than producing a broken artifact. Until a native macOS runtime is wired up, `./test.sh` validates the full compile/translate/assemble pipeline and explicitly **skips** the in-process execution smoke with a clear "alpha stub runtime" notice — so a stub runtime can never be silently mistaken for a working one. ## Repository layout diff --git a/publish.sh b/publish.sh index 2dfd05e..f586fd4 100755 --- a/publish.sh +++ b/publish.sh @@ -4,11 +4,34 @@ set -euo pipefail ROOTDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" RELEASE_DIR="${ROOTDIR}/release" +host_system() { + if [[ -n "${BLITZFORGE_PUBLISH_HOST_SYSTEM:-}" ]]; then + printf '%s\n' "${BLITZFORGE_PUBLISH_HOST_SYSTEM}" + return + fi + + uname -s +} + +require_supported_release_host() { + local system_name="${1:-$(host_system)}" + + case "${system_name}" in + Darwin) return 0 ;; + esac + + echo "publish.sh currently supports release archives only on macOS hosts." >&2 + echo "Linux source builds can stop at ./compile.sh until runtime/linker packaging exists there." >&2 + return 1 +} + host_archive_basename() { - case "$(uname -s)" in + case "${1:-$(host_system)}" in Darwin) echo "blitzforge-macos-arm64" ;; - Linux) echo "blitzforge-linux-host" ;; - *) echo "blitzforge-unix-host" ;; + *) + echo "Unsupported release host: ${1:-$(host_system)}" >&2 + return 1 + ;; esac } @@ -37,36 +60,44 @@ create_zip_archive() { exit 1 } -"${ROOTDIR}/compile.sh" +main() { + require_supported_release_host -rm -rf "${RELEASE_DIR}" -mkdir -p "${RELEASE_DIR}" + "${ROOTDIR}/compile.sh" -for dir in bin cfg games help media mediaview samples tutorials userlibs; do - if [[ -d "${ROOTDIR}/${dir}" ]]; then - rsync -a "${ROOTDIR}/${dir}/" "${RELEASE_DIR}/${dir}/" - fi -done + rm -rf "${RELEASE_DIR}" + mkdir -p "${RELEASE_DIR}" -if [[ -d "${ROOTDIR}/../../extras/vscode-blitz-forge" && -x "${ROOTDIR}/../../extras/vscode-blitz-forge/compile.sh" ]]; then - "${ROOTDIR}/../../extras/vscode-blitz-forge/compile.sh" - find "${ROOTDIR}/../../extras/vscode-blitz-forge" -maxdepth 1 -name '*.vsix' -exec cp {} "${RELEASE_DIR}/" \; -fi + for dir in bin cfg games help media mediaview samples tutorials userlibs; do + if [[ -d "${ROOTDIR}/${dir}" ]]; then + rsync -a "${ROOTDIR}/${dir}/" "${RELEASE_DIR}/${dir}/" + fi + done + + if [[ -d "${ROOTDIR}/../../extras/vscode-blitz-forge" && -x "${ROOTDIR}/../../extras/vscode-blitz-forge/compile.sh" ]]; then + "${ROOTDIR}/../../extras/vscode-blitz-forge/compile.sh" + find "${ROOTDIR}/../../extras/vscode-blitz-forge" -maxdepth 1 -name '*.vsix' -exec cp {} "${RELEASE_DIR}/" \; + fi -cat > "${RELEASE_DIR}/README.txt" <<'EOF' + cat > "${RELEASE_DIR}/README.txt" <<'EOF' BlitzForge is a compiler for an enhanced version of the Blitz3D language. It is a fork of the Blitz3D compiler and adds support for BlitzForge commands and syntax. You can develop with BlitzForge in Visual Studio Code by installing the bundled .vsix extension. EOF -ARCHIVE_BASENAME="$(host_archive_basename)" -ARCHIVE_PATH="${RELEASE_DIR}/${ARCHIVE_BASENAME}.zip" -PACKAGE_TMPDIR="$(mktemp -d "${TMPDIR:-/tmp}/blitzforge-package.XXXXXX")" -trap 'rm -rf "${PACKAGE_TMPDIR}"' EXIT -PACKAGE_ROOT="${PACKAGE_TMPDIR}/${ARCHIVE_BASENAME}" -mkdir -p "${PACKAGE_ROOT}" -rsync -a "${RELEASE_DIR}/" "${PACKAGE_ROOT}/" -rm -f "${ARCHIVE_PATH}" -create_zip_archive "${PACKAGE_TMPDIR}" "${ARCHIVE_BASENAME}" "${ARCHIVE_PATH}" - -echo "Created release archive: ${ARCHIVE_PATH}" + ARCHIVE_BASENAME="$(host_archive_basename)" + ARCHIVE_PATH="${RELEASE_DIR}/${ARCHIVE_BASENAME}.zip" + PACKAGE_TMPDIR="$(mktemp -d "${TMPDIR:-/tmp}/blitzforge-package.XXXXXX")" + trap 'rm -rf "${PACKAGE_TMPDIR}"' EXIT + PACKAGE_ROOT="${PACKAGE_TMPDIR}/${ARCHIVE_BASENAME}" + mkdir -p "${PACKAGE_ROOT}" + rsync -a "${RELEASE_DIR}/" "${PACKAGE_ROOT}/" + rm -f "${ARCHIVE_PATH}" + create_zip_archive "${PACKAGE_TMPDIR}" "${ARCHIVE_BASENAME}" "${ARCHIVE_PATH}" + + echo "Created release archive: ${ARCHIVE_PATH}" +} + +if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then + main "$@" +fi diff --git a/scripts/test_publish_contract.sh b/scripts/test_publish_contract.sh new file mode 100644 index 0000000..a0ab23c --- /dev/null +++ b/scripts/test_publish_contract.sh @@ -0,0 +1,56 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOTDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +source "${ROOTDIR}/publish.sh" + +fail() { + echo "FAIL: $*" >&2 + exit 1 +} + +assert_eq() { + local expected="$1" + local actual="$2" + local label="$3" + if [[ "${expected}" != "${actual}" ]]; then + fail "${label}: expected '${expected}', got '${actual}'" + fi +} + +assert_success() { + local label="$1" + shift + if ! "$@"; then + fail "${label}: command failed" + fi +} + +assert_failure_with_stderr() { + local expected="$1" + shift + local stderr_file + stderr_file="$(mktemp "${TMPDIR:-/tmp}/publish-contract.XXXXXX")" + if "$@" > /dev/null 2> "${stderr_file}"; then + rm -f "${stderr_file}" + fail "expected failure but command succeeded" + fi + if ! grep -Fq "${expected}" "${stderr_file}"; then + cat "${stderr_file}" >&2 + rm -f "${stderr_file}" + fail "stderr did not contain '${expected}'" + fi + rm -f "${stderr_file}" +} + +BLITZFORGE_PUBLISH_HOST_SYSTEM=Darwin +assert_eq "Darwin" "$(host_system)" "Darwin override" +assert_success "Darwin host is allowed" require_supported_release_host +assert_eq "blitzforge-macos-arm64" "$(host_archive_basename)" "Darwin archive basename" + +BLITZFORGE_PUBLISH_HOST_SYSTEM=Linux +assert_eq "Linux" "$(host_system)" "Linux override" +assert_failure_with_stderr "release archives only on macOS hosts" require_supported_release_host +assert_failure_with_stderr "Unsupported release host: Linux" host_archive_basename + +echo "publish.sh contract tests passed"