99e5641127
Pipeline (3 operator asks): - bump-release.sh: canonical orchestrator (forks + sources + external) - upgrade-forks.sh --to=<tag>: rebase forks with diverged-mode guard - bump-graphics-recipes.sh: map-driven group-aware graphics bumps - check-external-versions.sh: drift checker for Qt6/KF6/Plasma/Mesa/Wayland - refresh-fork-upstream-map.sh: append-only map updater with --check - post-checkout-version-sync.sh + install-git-hooks.sh: opt-in branch hook - external_version_lib.py: shared version-parsing/bumping library - external-upstream-map.toml: ~80 external package entries - bump-fork.sh: deprecated (REDBEAR_I_KNOW_BUMP_FORK_IS_DEPRECATED=1) - RELEASE-BUMP-WORKFLOW.md: operator runbook Quality fixes (8 defects from two independent audits): - blake2b stable cache keys (was hash(), non-portable) - atomic cache writes via os.replace - version_sort_key pre-release demotion (was sorting after finals) - apply_ver_transform re.error tolerance - grep || true (pipefail abort) - cd failure detection in upgrade-forks - sed URL escape (injection hardening) - refresh-fork-upstream-map last-row drop fix Doc cleanup: - Archive 5 obsolete plans to local/docs/archived/ - Remove 14 stale/superseded docs - Update 18 docs to reference bump-release.sh and fix inbound links - TOOLS.md drift fixes
256 lines
9.6 KiB
Bash
Executable File
256 lines
9.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
#
|
|
# ============================================================================
|
|
# DEPRECATED — DO NOT USE (2026-07-18, release-bump-pipeline.md Deliverable 4)
|
|
# ============================================================================
|
|
# This script is superseded by:
|
|
# - local/scripts/bump-release.sh (canonical orchestrator)
|
|
# - local/scripts/upgrade-forks.sh --to=... (per-fork source bump)
|
|
#
|
|
# WHY IT IS DEPRECATED:
|
|
# bump-fork.sh uses a WHOLESALE-REPLACEMENT model: it clones a fresh
|
|
# upstream tag, applies patch files from local/patches/<comp>/, and then
|
|
# SWAPS the entire local/sources/<comp>/ directory with the new tree.
|
|
# This DESTROYS any committed fork work that is not also present as a
|
|
# patch file under local/patches/<comp>/ — including commits made
|
|
# directly to the submodule/<comp> branch (the path-fork model that
|
|
# replaced overlay patches in 2026-06).
|
|
#
|
|
# Concretely: kernel, relibc, base, bootloader, installer, redoxfs, and
|
|
# userutils now carry Red Bear changes as direct commits on their
|
|
# `submodule/<component>` branches, NOT as patch files. Running
|
|
# bump-fork.sh on any of them would silently discard that work.
|
|
#
|
|
# RETENTION POLICY:
|
|
# This file is KEPT for historical reference only, per the project's
|
|
# never-delete rule. The runtime guard below prevents accidental use.
|
|
# Its logic is otherwise unchanged.
|
|
#
|
|
# ESCAPE HATCH (operators only, with eyes open):
|
|
# REDBEAR_I_KNOW_BUMP_FORK_IS_DEPRECATED=1 ./local/scripts/bump-fork.sh ...
|
|
# ============================================================================
|
|
#
|
|
# bump-fork.sh — Auto-bump a local fork to match upstream version
|
|
#
|
|
# Usage: bump-fork.sh <component> [--version=X.Y.Z]
|
|
#
|
|
# If --version is provided, bumps to that version.
|
|
# If --version is omitted, queries Cargo to determine the required version
|
|
# from the build graph.
|
|
#
|
|
# Implements: AGENTS.md "Local Fork Priority and Version Sync (MANDATORY)"
|
|
|
|
set -euo pipefail
|
|
|
|
# ---- Runtime deprecation guard -------------------------------------------
|
|
# Refuse to run unless the operator explicitly acknowledges the
|
|
# deprecation by exporting REDBEAR_I_KNOW_BUMP_FORK_IS_DEPRECATED=1.
|
|
# Without the env var, print the deprecation explanation to stderr and
|
|
# exit 1 BEFORE any potentially destructive operation runs.
|
|
if [[ "${REDBEAR_I_KNOW_BUMP_FORK_IS_DEPRECATED:-0}" != "1" ]]; then
|
|
cat >&2 <<'EOF'
|
|
============================================================================
|
|
bump-fork.sh is DEPRECATED (release-bump-pipeline.md Deliverable 4).
|
|
|
|
Its wholesale-replacement model destroys committed fork work that is not
|
|
also present as a patch file under local/patches/<comp>/. Under the current
|
|
path-fork model, kernel/relibc/base/bootloader/installer/redoxfs/userutils
|
|
carry Red Bear changes as direct commits on submodule/<component> branches
|
|
— running this script on any of them would silently discard that work.
|
|
|
|
Use instead:
|
|
./local/scripts/bump-release.sh # canonical orchestrator
|
|
./local/scripts/upgrade-forks.sh --to=<tag> # per-fork source bump
|
|
|
|
This file is retained for historical reference per the never-delete rule.
|
|
|
|
To override (operators only, with full understanding of the risk):
|
|
REDBEAR_I_KNOW_BUMP_FORK_IS_DEPRECATED=1 ./local/scripts/bump-fork.sh ...
|
|
============================================================================
|
|
EOF
|
|
exit 1
|
|
fi
|
|
|
|
# Derive Red Bear OS version from the current git branch name.
|
|
# Branch "0.3.1" → BRANCH_VERSION="0.3.1". Same pattern as
|
|
# local/scripts/build-redbear.sh:158-165. Falls back to "0.0.0" if
|
|
# the branch name doesn't match semver.
|
|
BRANCH_VERSION=$(git -C "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" branch --show-current 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 || true)
|
|
BRANCH_VERSION="${BRANCH_VERSION:-0.0.0}"
|
|
export BRANCH_VERSION
|
|
|
|
COMPONENT="${1:-}"
|
|
if [[ -z "$COMPONENT" ]]; then
|
|
echo "Usage: $0 <component> [--version=X.Y.Z]"
|
|
echo ""
|
|
echo "Components with local forks:"
|
|
for d in local/sources/*/; do
|
|
if [[ -d "$d" ]] && [[ -f "${d}Cargo.toml" ]]; then
|
|
echo " $(basename "$d")"
|
|
fi
|
|
done
|
|
exit 1
|
|
fi
|
|
|
|
shift
|
|
|
|
VERSION=""
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--version=*)
|
|
VERSION="${1#*=}"
|
|
shift
|
|
;;
|
|
*)
|
|
echo "Unknown option: $1" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
LOCAL_DIR="local/sources/${COMPONENT}"
|
|
RECIPE_DIR="recipes/core/${COMPONENT}"
|
|
|
|
if [[ ! -d "$LOCAL_DIR" ]]; then
|
|
echo "ERROR: $LOCAL_DIR does not exist" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# Detect current local version
|
|
if [[ -f "${LOCAL_DIR}/Cargo.toml" ]]; then
|
|
CURRENT_VERSION=$(grep -E '^version\s*=' "${LOCAL_DIR}/Cargo.toml" | head -1 | sed 's/.*"\(.*\)".*/\1/')
|
|
echo "Current local version: ${CURRENT_VERSION:-unknown}"
|
|
else
|
|
echo "WARNING: ${LOCAL_DIR}/Cargo.toml not found — not a Cargo crate?"
|
|
CURRENT_VERSION=""
|
|
fi
|
|
|
|
# Detect required version from build graph if not specified
|
|
if [[ -z "$VERSION" ]]; then
|
|
echo "Querying build graph for required version of ${COMPONENT}..."
|
|
|
|
# Search Cargo.lock files for the required version
|
|
REQUIRED_VERSION=""
|
|
while IFS= read -r lockfile; do
|
|
# Look for [[package]] entries that match this component
|
|
entry=$(awk '
|
|
/^name = "'"${COMPONENT}"'"$/ { found=1; next }
|
|
found && /^version = / { gsub(/"/, ""); print; exit }
|
|
' "$lockfile" 2>/dev/null)
|
|
if [[ -n "$entry" ]]; then
|
|
REQUIRED_VERSION="$entry"
|
|
break
|
|
fi
|
|
done < <(find . -name 'Cargo.lock' -not -path '*/.git/*' 2>/dev/null)
|
|
|
|
if [[ -z "$REQUIRED_VERSION" ]]; then
|
|
echo "ERROR: Could not determine required version for ${COMPONENT}" >&2
|
|
echo " Pass --version=X.Y.Z explicitly" >&2
|
|
exit 1
|
|
fi
|
|
|
|
VERSION="$REQUIRED_VERSION"
|
|
echo "Required version (from Cargo.lock): ${VERSION}"
|
|
fi
|
|
|
|
# Check if bump is needed
|
|
if [[ -n "$CURRENT_VERSION" ]] && [[ "$CURRENT_VERSION" == "$VERSION" ]]; then
|
|
echo "Local fork already at v${VERSION} — no bump needed"
|
|
exit 0
|
|
fi
|
|
|
|
echo "Bumping ${COMPONENT}: v${CURRENT_VERSION:-unknown} → v${VERSION}"
|
|
|
|
# Fetch upstream source at the required version
|
|
echo "Fetching upstream source at v${VERSION}..."
|
|
|
|
# Find the upstream repo URL from the recipe
|
|
if [[ -f "${RECIPE_DIR}/recipe.toml" ]]; then
|
|
UPSTREAM_GIT=$(grep -E '^git\s*=' "${RECIPE_DIR}/recipe.toml" | head -1 | sed 's/.*"\(.*\)".*/\1/')
|
|
fi
|
|
|
|
if [[ -z "${UPSTREAM_GIT:-}" ]]; then
|
|
echo "ERROR: Cannot determine upstream git URL from ${RECIPE_DIR}/recipe.toml" >&2
|
|
echo " Set up the recipe or pass --upstream-git=<url>" >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo "Upstream git: ${UPSTREAM_GIT}"
|
|
|
|
# Fetch into a staging directory
|
|
STAGING_DIR="/tmp/redbear-bump-${COMPONENT}-$$"
|
|
trap "rm -rf ${STAGING_DIR}" EXIT
|
|
|
|
echo "Cloning ${UPSTREAM_GIT} at v${VERSION} into ${STAGING_DIR}..."
|
|
if ! git clone --depth 1 --branch "v${VERSION}" "${UPSTREAM_GIT}" "${STAGING_DIR}" 2>&1; then
|
|
echo "WARNING: clone with tag v${VERSION} failed, trying without tag..."
|
|
if ! git clone --depth 1 "${UPSTREAM_GIT}" "${STAGING_DIR}" 2>&1; then
|
|
echo "ERROR: git clone of ${UPSTREAM_GIT} failed" >&2
|
|
exit 1
|
|
fi
|
|
cd "${STAGING_DIR}"
|
|
git fetch --tags --quiet
|
|
if git rev-parse --verify "refs/tags/v${VERSION}" >/dev/null 2>&1; then
|
|
git checkout "v${VERSION}" --quiet
|
|
elif git rev-parse --verify "refs/tags/${VERSION}" >/dev/null 2>&1; then
|
|
git checkout "${VERSION}" --quiet
|
|
else
|
|
echo "WARNING: tag v${VERSION} not found — using default branch HEAD"
|
|
fi
|
|
cd - >/dev/null
|
|
else
|
|
cd "${STAGING_DIR}"
|
|
git fetch --tags --quiet 2>/dev/null || true
|
|
cd - >/dev/null
|
|
fi
|
|
|
|
# Apply Red Bear patches
|
|
PATCH_DIR="local/patches/${COMPONENT}"
|
|
if [[ -d "$PATCH_DIR" ]]; then
|
|
echo "Applying Red Bear patches from ${PATCH_DIR}..."
|
|
for patch in "${PATCH_DIR}"/*.patch; do
|
|
if [[ -f "$patch" ]]; then
|
|
echo " Applying $(basename "$patch")..."
|
|
if ! patch -p1 -d "${STAGING_DIR}" --dry-run < "$patch" >/dev/null 2>&1; then
|
|
echo "ERROR: Patch $(basename "$patch") fails to apply to upstream v${VERSION}" >&2
|
|
echo " Manual intervention required — patch may need rebasing" >&2
|
|
exit 1
|
|
fi
|
|
patch -p1 -d "${STAGING_DIR}" < "$patch"
|
|
fi
|
|
done
|
|
fi
|
|
|
|
# Update version in Cargo.toml
|
|
if [[ -f "${STAGING_DIR}/Cargo.toml" && -n "${CURRENT_VERSION}" ]]; then
|
|
escaped_current=$(printf '%s\n' "${CURRENT_VERSION}" | sed 's/[.[\*^$()+?{|\\]/\\&/g')
|
|
sed -i "s/^version = \"${escaped_current}\"/version = \"${VERSION}+rb${BRANCH_VERSION:-0.0.0}\"/" "${STAGING_DIR}/Cargo.toml"
|
|
fi
|
|
|
|
# Replace local fork contents
|
|
echo "Updating ${LOCAL_DIR}..."
|
|
OLD_DIR="${LOCAL_DIR}.old-${$}"
|
|
if ! mv "${STAGING_DIR}" "${LOCAL_DIR}.new-${$}" 2>/dev/null; then
|
|
echo "ERROR: cannot move staging dir — disk full or permission denied" >&2
|
|
rm -rf "${STAGING_DIR}"
|
|
exit 1
|
|
fi
|
|
mv "${LOCAL_DIR}" "${OLD_DIR}" && mv "${LOCAL_DIR}.new-${$}" "${LOCAL_DIR}"
|
|
if [[ $? -ne 0 ]]; then
|
|
echo "ERROR: swap failed — restoring original" >&2
|
|
mv "${OLD_DIR}" "${LOCAL_DIR}" 2>/dev/null || true
|
|
rm -rf "${LOCAL_DIR}.new-${$}"
|
|
exit 1
|
|
fi
|
|
rm -rf "${OLD_DIR}"
|
|
|
|
echo ""
|
|
echo "SUCCESS: ${COMPONENT} bumped to v${VERSION}"
|
|
echo ""
|
|
echo "Next steps:"
|
|
echo " 1. cd ${LOCAL_DIR}"
|
|
echo " 2. git diff (verify patches applied correctly)"
|
|
echo " 3. git add -A && git commit -m 'bump: ${COMPONENT} v${CURRENT_VERSION} -> v${VERSION}'"
|
|
echo " 4. git push origin submodule/${COMPONENT}"
|
|
echo " 5. Update local/fork-upstream-map.toml if the upstream tag changed"
|
|
echo " 5. Rebuild affected packages: ./local/scripts/build-redbear.sh redbear-mini" |