feat(tools): directed panspermia inspired colonization scripts
Some checks failed
railiance-tests / smoke (push) Has been cancelled

This commit is contained in:
2025-09-13 00:11:18 +02:00
parent be750b005b
commit 75d11583e4
4 changed files with 426 additions and 0 deletions

62
tools/README_tools.md Normal file
View File

@@ -0,0 +1,62 @@
# 🌱 Railiance Tools — Directed Panspermia Model
Railiance bootstraps infrastructure in a way inspired by **directed panspermia**
the idea of life being intentionally seeded across the cosmos.
Here, instead of biology, we seed **infrastructure-as-code** into blank environments.
---
## 🧬 Core Concepts
- **Parent Body** — an existing Railiance repo (the source of life).
- **Seed** — the minimal set of instructions/scripts to reproduce the repo in a new environment.
- **Spore** — a portable, bundled package of the Seed (self-contained, easy to transfer).
- **Target Environment** — a blank host (a sterile world waiting for life).
- **Biogenesis** — the process of unpacking a Spore and bootstrapping the environment.
- **Evolutionary Adaptation** — further provisioning, testing, and tuning specific to the host.
---
## 🛠️ Toolchain Overview
### `create_railiance_repo.sh`
- Creates a new Railiance repo in Gitea (under user or org).
- Acts like the *egg cell*: it defines the first container for life.
### `furnish_railiance_repo.sh`
- Idempotently sets up repo housekeeping files (LICENSE, README, .editorconfig, etc.).
- Brings the repo to a clean, opinionated state.
- Equivalent to providing the *genetic code*.
### `build_spore.sh`
- Packages the Seed into a **Spore bundle** (tar.gz).
- Includes creation/furnishing scripts, docs, and metadata.
- Like enclosing life into a *protective capsule* for travel.
### `seed_node.sh`
- Run on a blank host to unpack a Spore.
- Performs **Biogenesis**: installs prerequisites, clones the repo, and executes bootstrap steps.
- Like a *spore germinating* on a fertile planet.
---
## 🚀 Lifecycle
1. **Create** a repo with `create_railiance_repo.sh`.
2. **Furnish** it into a clean Railiance structure with `furnish_railiance_repo.sh`.
3. **Build** a distributable bundle with `build_spore.sh`.
4. **Seed** new environments with `seed_node.sh`.
---
## 🌍 Why Panspermia?
This model emphasizes:
- **Reproducibility**: every host can be bootstrapped identically from a Spore.
- **Federation**: Spores can be sent to many environments (different orgs, clusters, or even air-gapped hosts).
- **Resilience**: infrastructure survives and adapts, no matter the environment.
- **Storytelling**: by using biological metaphors, we keep the process intuitive and memorable.
---
✦ Railiance is not just code — its a way of letting infrastructure **colonize new worlds**.

29
tools/build_spore.sh Normal file
View File

@@ -0,0 +1,29 @@
#!/usr/bin/env bash
# tools/build_spore.sh
# Package a "Spore" bundle: minimal bootstrap seed + furnishing scripts + metadata
set -euo pipefail
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
outdir="${repo_root}/dist"
mkdir -p "${outdir}"
timestamp="$(date -u +%Y%m%dT%H%M%SZ)"
spore_name="railiance_spore_${timestamp}.tar.gz"
spore_path="${outdir}/${spore_name}"
echo "[*] Building spore bundle → ${spore_path}"
# Metadata file
cat > "${outdir}/SPORE_METADATA.txt" <<META
Railiance Spore
---------------
Timestamp: ${timestamp}
Repo: $(basename "${repo_root}")
Commit: $(git -C "${repo_root}" rev-parse HEAD 2>/dev/null || echo "N/A")
META
# Bundle essential files
tar -czf "${spore_path}" -C "${repo_root}" tools/create_railiance_repo.sh tools/furnish_railiance_repo.sh tools/build_spore.sh tools/seed_node.sh LICENSE README.md .editorconfig .gitattributes .gitignore docs/ -C "${outdir}" SPORE_METADATA.txt
echo "[✓] Spore bundle created: ${spore_path}"

View File

@@ -0,0 +1,199 @@
#!/usr/bin/env bash
# tools/furnish_railiance_repo.sh
# Idempotently "furnishes" the repo with license, readmes, and housekeeping files.
set -euo pipefail
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
ensure_file() { # ensure_file <path> <here-doc label> [mode]
local path="$1"; shift
local label="$1"; shift
local mode="${1:-}"
if [[ -f "${path}" ]]; then
echo "[=] exists: ${path}"
else
echo "[+] create: ${path}"
mkdir -p "$(dirname "${path}")"
eval "cat <<'${label}' > '${path}'"
if [[ -n "${mode}" ]]; then chmod "${mode}" "${path}"; fi
fi
}
append_once() { # append_once <path> <needle> <text>
local path="$1" needle="$2" text="$3"
grep -qF "${needle}" "${path}" 2>/dev/null || { echo "${text}" >> "${path}"; echo "[+] append → ${path}"; }
}
# LICENSE (MIT)
ensure_file "${repo_root}/LICENSE" LIC <<'LIC'
MIT License
Copyright (c) 2025 Railiance Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
LIC
# Root README with badge (only if missing)
ensure_file "${repo_root}/README.md" RREAD <<'RREAD'
# Railiance Bootstrap
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
Railiance is an opinionated **Infrastructure-as-Code framework** —
think *Rails for Ops*: convention over configuration, reproducibility first.
This repo (`railiance-bootstrap`) is the **entry point**:
from two bare Linux servers, a Git repo, and credentials, you can rebuild
a fully automated Kubernetes-based environment.
RREAD
# docs/README
ensure_file "${repo_root}/docs/README.md" DREAD <<'DREAD'
# Railiance Documentation
Welcome to **Railiance** — an opinionated framework for Infrastructure-as-Code.
Think of it as *Rails for Ops*: convention over configuration, productivity first.
DREAD
# CONTRIBUTING
ensure_file "${repo_root}/docs/CONTRIBUTING.md" CONTRIB <<'CONTRIB'
# Contributing to Railiance
(…short rules: no secrets, LF endings, PRs w/ tests…)
CONTRIB
# .editorconfig
ensure_file "${repo_root}/.editorconfig" ECONF <<'ECONF'
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = space
indent_size = 2
[*.md]
trim_trailing_whitespace = false
[*.{yml,yaml}]
indent_style = space
indent_size = 2
[*.sh]
indent_style = space
indent_size = 2
[*.py]
indent_style = space
indent_size = 4
ECONF
# .gitattributes
ensure_file "${repo_root}/.gitattributes" GATTR <<'GATTR'
* text=auto eol=lf
*.sh text eol=lf
*.yml text eol=lf
*.yaml text eol=lf
*.md text eol=lf
*.png binary
*.jpg binary
*.jpeg binary
*.gif binary
*.svg binary
*.ico binary
*.pdf binary
*.zip binary
*.tar.gz binary
*.tgz binary
.gitattributes text eol=lf
.editorconfig text eol=lf
GATTR
# .gitignore
ensure_file "${repo_root}/.gitignore" GIGN <<'GIGN'
.DS_Store
Thumbs.db
*.swp
*.swo
*.bak
*.tmp
*~
__pycache__/
*.pyc
*.pyo
*.pyd
*.egg-info/
.eggs/
.venv/
venv/
env/
node_modules/
npm-debug.log
yarn-debug.log
yarn-error.log
.pnpm-debug.log
*.retry
inventory/
hosts
.secrets/
.vault_pass.txt
charts/*.tgz
.helm/
kustomize-build/
.kube/
*.kubeconfig
.terraform/
terraform.tfstate
terraform.tfstate.backup
*.tfvars
logs/
*.log
.coverage
coverage.xml
htmlcov/
.junit/
*.out
*.err
.gitattributes.lock
.editorconfig.lock
.railiance_gitea.conf
.vscode/
.idea/
*.iml
GIGN
# tools/README
ensure_file "${repo_root}/tools/README.md" TREAD <<'TREAD'
# Railiance Tools
- `create_railiance_repo.sh` — create a Gitea repo (user/org).
- `furnish_railiance_repo.sh` — idempotently add license/housekeeping to this repo.
- `build_spore.sh` — produce a portable seed bundle (see panspermia model).
- `seed_node.sh` — run on a blank host to kick off biogenesis.
TREAD
echo "[✓] Furnishing complete."

136
tools/seed_node.sh Normal file
View File

@@ -0,0 +1,136 @@
#!/usr/bin/env bash
# tools/seed_node.sh
# Railiance Seed — kick off biogenesis on a blank (or nearly blank) host.
#
# Responsibilities:
# - Ensure minimal prerequisites (curl, git, jq)
# - Discover metadata (panspermia.json or env vars)
# - Clone or update the parent repo (default: railiance-bootstrap)
# - Run furnishing (idempotent) to align housekeeping
# - (Optional) handoff to further bootstrap steps
#
# Usage examples:
# ./tools/seed_node.sh
# REPO_URL=https://git.example.com/org/railiance-bootstrap.git ./tools/seed_node.sh
# ./tools/seed_node.sh --repo-dir /srv/railiance --branch main
#
# Notes:
# - No secrets are written or echoed by this script.
# - Git authentication relies on your environment (SSH keys or credential helper).
set -euo pipefail
# --------- defaults & flags ----------
REPO_DIR="${REPO_DIR:-railiance-bootstrap}"
BRANCH="${BRANCH:-main}"
META_PATH="${META_PATH:-}" # optional explicit path to panspermia.json
QUIET=false
while [[ $# -gt 0 ]]; do
case "$1" in
--repo-dir) REPO_DIR="${2:?}"; shift 2 ;;
--branch) BRANCH="${2:?}"; shift 2 ;;
--meta) META_PATH="${2:?}"; shift 2 ;;
-q|--quiet) QUIET=true; shift ;;
-h|--help)
sed -n '1,120p' "$0" | sed -n '1,/^set -euo pipefail/p'
exit 0 ;;
*) echo "Unknown arg: $1" >&2; exit 2 ;;
esac
done
log() { $QUIET || echo "$@"; }
need() {
command -v "$1" >/dev/null 2>&1 && return 0
log "[*] Installing $1 ..."
if command -v apt-get >/dev/null 2>&1; then
sudo apt-get update -y && sudo apt-get install -y "$1"
elif command -v dnf >/dev/null 2>&1; then
sudo dnf install -y "$1"
elif command -v yum >/dev/null 2>&1; then
sudo yum install -y "$1"
else
echo "ERROR: package manager not found to install $1" >&2
exit 1
fi
}
# prerequisites
need curl
need git
command -v jq >/dev/null 2>&1 || need jq
# --------- discover metadata ----------
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
DEFAULT_META="${SCRIPT_DIR}/../panspermia.json"
REPO_URL="${REPO_URL:-}"
if [[ -z "${REPO_URL}" ]]; then
# read metadata file (explicit > default > none)
SRC_META=""
if [[ -n "${META_PATH}" && -f "${META_PATH}" ]]; then
SRC_META="${META_PATH}"
elif [[ -f "${DEFAULT_META}" ]]; then
SRC_META="${DEFAULT_META}"
fi
if [[ -n "${SRC_META}" ]]; then
log "[=] Using metadata: ${SRC_META}"
REPO_URL="$(jq -r '.parent_body.repo_url // empty' "${SRC_META}")"
BRANCH_FROM_META="$(jq -r '.parent_body.branch // empty' "${SRC_META}")" || true
if [[ -n "${BRANCH_FROM_META}" ]]; then BRANCH="${BRANCH_FROM_META}"; fi
fi
fi
if [[ -z "${REPO_URL}" ]]; then
echo "ERROR: No REPO_URL provided and no panspermia metadata found." >&2
echo "Provide one of:" >&2
echo " - env REPO_URL=https://git.example.com/org/railiance-bootstrap.git" >&2
echo " - or a panspermia.json with .parent_body.repo_url" >&2
exit 1
fi
log "[*] Target repo: ${REPO_URL} (branch: ${BRANCH})"
log "[*] Local dir : ${REPO_DIR}"
# --------- clone or update ----------
if [[ -d "${REPO_DIR}/.git" ]]; then
log "[=] Repo dir exists. Fetching updates ..."
(
cd "${REPO_DIR}"
git remote -v
git fetch --all --tags
git checkout "${BRANCH}"
git pull --ff-only origin "${BRANCH}" || true
)
else
log "[+] Cloning repository ..."
git clone --branch "${BRANCH}" "${REPO_URL}" "${REPO_DIR}"
fi
# --------- furnishing ----------
if [[ -x "${REPO_DIR}/tools/furnish_railiance_repo.sh" ]]; then
log "[*] Running furnishing script (idempotent) ..."
bash "${REPO_DIR}/tools/furnish_railiance_repo.sh"
else
log "[!] Furnishing script not found at ${REPO_DIR}/tools/furnish_railiance_repo.sh — skipping."
fi
# --------- placeholder for next steps ----------
cat <<'NEXT'
[✓] Seed completed.
Next steps (manual, for now):
1) Review the repo at $REPO_DIR
2) Configure host inventory and credentials (kept local, never committed)
3) Run the initial bootstrap playbook (e.g., ansible/bootstrap.yml)
4) Prepare GitOps operator (ArgoCD/Flux) pointing to this repo
Hints:
- To use SSH instead of HTTPS, set REPO_URL=git@your-gitea:org/railiance-bootstrap.git
- If using HTTPS, set up 'git config --global credential.helper cache|store'
- For air-gapped: copy a Spore bundle, extract, then run this seed script
NEXT