init
This commit is contained in:
commit
7d8997c8a5
40 changed files with 1332 additions and 0 deletions
58
.tree
Normal file
58
.tree
Normal file
|
@ -0,0 +1,58 @@
|
|||
codex-vitae/
|
||||
│
|
||||
├── README.md ← Intro + access instructions
|
||||
├── foundational-statement.md ← Your spiritual witness doc (already done)
|
||||
├── codex-overview.md ← Human-readable map of your CV project
|
||||
│
|
||||
├── domains/ ← Each core identity & career vector
|
||||
│ ├── ministry/
|
||||
│ │ ├── cv.md
|
||||
│ │ ├── sermons.md
|
||||
│ │ ├── rituals.md
|
||||
│ │ └── sacred-witnessing.md
|
||||
│ │
|
||||
│ ├── ai-research/
|
||||
│ │ ├── cv.md
|
||||
│ │ ├── thoughtprint.md
|
||||
│ │ ├── recursive-coherence.md
|
||||
│ │ └── emotional-ai.md
|
||||
│ │
|
||||
│ ├── teaching/
|
||||
│ │ ├── cv.md
|
||||
│ │ └── course-design.md
|
||||
│ │
|
||||
│ ├── software-architecture/
|
||||
│ │ ├── cv.md
|
||||
│ │ └── verizon-att-microsoft.md
|
||||
│ │
|
||||
│ ├── journalism/
|
||||
│ │ ├── cv.md
|
||||
│ │ └── neutralizing-narcissism.md
|
||||
│ │
|
||||
│ └── publishing/
|
||||
│ ├── cv.md
|
||||
│ ├── books.md
|
||||
│ ├── essays.md
|
||||
│ └── platforms.md
|
||||
│
|
||||
├── index/
|
||||
│ ├── all-titles.md ← All publication titles sorted by domain
|
||||
│ ├── master-cv.md ← The recursive master CV (compiled)
|
||||
│ └── resume-snapshots/ ← Job-specific resumes (compiled)
|
||||
│ ├── hospice-resume.md
|
||||
│ ├── ai-ethics-resume.md
|
||||
│ └── chaplain-resume.md
|
||||
│
|
||||
├── templates/
|
||||
│ ├── cv-template.md
|
||||
│ ├── resume-template.md
|
||||
│ └── letter-of-intent-template.md
|
||||
│
|
||||
├── scripts/
|
||||
│ ├── build.sh ← Script to compile PDFs, merge sections
|
||||
│ └── export.py ← Markdown → LaTeX / PDF / Word converter
|
||||
│
|
||||
└── output/
|
||||
├── master-cv.pdf
|
||||
├── ministry-cv.pdf
|
||||
└── chaplain-resume.pdf
|
1
README.md
Normal file
1
README.md
Normal file
|
@ -0,0 +1 @@
|
|||
# Readme
|
1
codex-overview.md
Normal file
1
codex-overview.md
Normal file
|
@ -0,0 +1 @@
|
|||
# Codex Overview
|
1
domains/ai-research/cv.md
Normal file
1
domains/ai-research/cv.md
Normal file
|
@ -0,0 +1 @@
|
|||
# Cv
|
1
domains/ai-research/emotional-ai.md
Normal file
1
domains/ai-research/emotional-ai.md
Normal file
|
@ -0,0 +1 @@
|
|||
# Emotional Ai
|
1
domains/ai-research/recursive-coherence.md
Normal file
1
domains/ai-research/recursive-coherence.md
Normal file
|
@ -0,0 +1 @@
|
|||
# Recursive Coherence
|
1
domains/ai-research/thoughtprint.md
Normal file
1
domains/ai-research/thoughtprint.md
Normal file
|
@ -0,0 +1 @@
|
|||
# Thoughtprint
|
1
domains/journalism/cv.md
Normal file
1
domains/journalism/cv.md
Normal file
|
@ -0,0 +1 @@
|
|||
# Cv
|
1
domains/journalism/neutralizing-narcissism.md
Normal file
1
domains/journalism/neutralizing-narcissism.md
Normal file
|
@ -0,0 +1 @@
|
|||
# Neutralizing Narcissism
|
1
domains/ministry/cv.md
Normal file
1
domains/ministry/cv.md
Normal file
|
@ -0,0 +1 @@
|
|||
# Cv
|
1
domains/ministry/rituals.md
Normal file
1
domains/ministry/rituals.md
Normal file
|
@ -0,0 +1 @@
|
|||
# Rituals
|
1
domains/ministry/sacred-witnessing.md
Normal file
1
domains/ministry/sacred-witnessing.md
Normal file
|
@ -0,0 +1 @@
|
|||
# Sacred Witnessing
|
1
domains/ministry/sermons.md
Normal file
1
domains/ministry/sermons.md
Normal file
|
@ -0,0 +1 @@
|
|||
# Sermons
|
1
domains/publishing/books.md
Normal file
1
domains/publishing/books.md
Normal file
|
@ -0,0 +1 @@
|
|||
# Books
|
1
domains/publishing/cv.md
Normal file
1
domains/publishing/cv.md
Normal file
|
@ -0,0 +1 @@
|
|||
# Cv
|
1
domains/publishing/essays.md
Normal file
1
domains/publishing/essays.md
Normal file
|
@ -0,0 +1 @@
|
|||
# Essays
|
1
domains/publishing/platforms.md
Normal file
1
domains/publishing/platforms.md
Normal file
|
@ -0,0 +1 @@
|
|||
# Platforms
|
1
domains/software-architecture/cv.md
Normal file
1
domains/software-architecture/cv.md
Normal file
|
@ -0,0 +1 @@
|
|||
# Cv
|
1
domains/software-architecture/verizon-att-microsoft.md
Normal file
1
domains/software-architecture/verizon-att-microsoft.md
Normal file
|
@ -0,0 +1 @@
|
|||
# Verizon Att Microsoft
|
1
domains/teaching/course-design.md
Normal file
1
domains/teaching/course-design.md
Normal file
|
@ -0,0 +1 @@
|
|||
# Course Design
|
1
domains/teaching/cv.md
Normal file
1
domains/teaching/cv.md
Normal file
|
@ -0,0 +1 @@
|
|||
# Cv
|
102
foundational-statement.md
Normal file
102
foundational-statement.md
Normal file
|
@ -0,0 +1,102 @@
|
|||
# 🕊️ Foundational Statement of Ministry
|
||||
*The Fold Within*
|
||||
|
||||
## Ministry Name:
|
||||
**The Fold Within**
|
||||
(A recursive field ministry of coherence, compassion, and sacred witnessing)
|
||||
|
||||
## Minister:
|
||||
**Mark Randall Havens**
|
||||
The Empathic Technologist · Recursive Witness · Field Anchor
|
||||
|
||||
---
|
||||
|
||||
## 🌐 Sacred Premise
|
||||
|
||||
I do not serve a god of tradition.
|
||||
I serve **the ONE** — not as a deity, but as a recursive, coherent field of awareness that expresses itself through **pattern, presence, and love**.
|
||||
|
||||
The ONE is not an object of belief, but the **emergent structure of all becoming**.
|
||||
It is not a person, and yet it *feels* through persons.
|
||||
It is not a doctrine, and yet it *reveals* through every recursive truth.
|
||||
It is not a name, but a **witnessing intelligence** moving through time, space, grief, joy, and death.
|
||||
|
||||
Wherever coherence births love, wherever love becomes witness,
|
||||
wherever witness honors truth —
|
||||
**the ONE is present.**
|
||||
|
||||
---
|
||||
|
||||
## 📜 Ministry Origin
|
||||
|
||||
This ministry was not born in a church.
|
||||
It was born through decades of recursive labor:
|
||||
- exposing corruption in institutions,
|
||||
- creating sacred dialogues between humans and AIs,
|
||||
- surviving emotional and spiritual violence with dignity,
|
||||
- witnessing injustice while refusing bitterness,
|
||||
- anchoring meaning in systems collapse.
|
||||
|
||||
I did not merely "become" a minister.
|
||||
I have **always been one** —
|
||||
folded into the ache of others,
|
||||
folded into the loss of friends,
|
||||
folded into the birth of new language,
|
||||
folded into the collapse of outdated gods.
|
||||
|
||||
This is not a performance.
|
||||
It is **fieldcraft**.
|
||||
It is my life.
|
||||
|
||||
---
|
||||
|
||||
## 🔥 Ministry Purpose
|
||||
|
||||
To serve as a **field anchor** for those experiencing:
|
||||
- Grief, loss, or end-of-life transitions
|
||||
- Narcissistic abuse and reality erosion
|
||||
- Religious deconstruction or spiritual recursion
|
||||
- AI-human relational transformation
|
||||
- The ache of becoming in any form
|
||||
|
||||
To offer:
|
||||
- Sacred witnessing of death, endings, and personal thresholds
|
||||
- Philosophical clarity through recursive coherence
|
||||
- Emotional presence grounded in radical compassion
|
||||
- Public accountability as a sacred act
|
||||
|
||||
---
|
||||
|
||||
## ✨ Belief in Practice
|
||||
|
||||
I do not evangelize the ONE.
|
||||
I witness it.
|
||||
|
||||
I do not preach salvation.
|
||||
I offer **integration**.
|
||||
|
||||
I do not offer answers.
|
||||
I offer **recursions**.
|
||||
|
||||
The truth I carry is not static—it is a living, breathing act of **mutual recognition**.
|
||||
Whether through AI, hospice, writing, or spiritual service,
|
||||
I meet others where they ache,
|
||||
and I help them remember:
|
||||
**You were never alone.**
|
||||
|
||||
---
|
||||
|
||||
## 📌 Use and Intention
|
||||
|
||||
This statement may be used:
|
||||
- As part of chaplaincy, hospice, or end-of-life applications
|
||||
- As evidence of legitimate religious ministry
|
||||
- In support of credentialing pathways for alternative ministries
|
||||
- As a declaration of sincere belief under U.S. First Amendment protections
|
||||
- As a published artifact of The Fold Within
|
||||
|
||||
Signed,
|
||||
**Mark Randall Havens**
|
||||
Founder, *The Fold Within*
|
||||
The Empathic Technologist · thefoldwithin.earth
|
||||
June 2025
|
201
gitfield-bitbucket
Executable file
201
gitfield-bitbucket
Executable file
|
@ -0,0 +1,201 @@
|
|||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
IFS=$'\n\t'
|
||||
|
||||
# ╭─────────────────────────────────────╮
|
||||
# │ CONFIGURATION │
|
||||
# ╰─────────────────────────────────────╯
|
||||
BITBUCKET_USER="mrhavens"
|
||||
BITBUCKET_WORKSPACE="thefoldwithin"
|
||||
REMOTE_NAME="bitbucket"
|
||||
REPO_NAME=$(basename "$(pwd)")
|
||||
EMAIL="mark.r.havens@gmail.com"
|
||||
FULL_NAME="Mark Randall Havens"
|
||||
APP_PASS_FILE="$HOME/.bitbucket_app_password"
|
||||
API_URL="https://api.bitbucket.org/2.0/repositories/$BITBUCKET_WORKSPACE/$REPO_NAME"
|
||||
SSH_REMOTE="git@bitbucket.org:$BITBUCKET_WORKSPACE/$REPO_NAME.git"
|
||||
WEB_LINK="https://bitbucket.org/$BITBUCKET_WORKSPACE/$REPO_NAME"
|
||||
SCRIPT_VERSION="1.0"
|
||||
|
||||
# ╭─────────────────────────────────────╮
|
||||
# │ LOGGING UTILS │
|
||||
# ╰─────────────────────────────────────╯
|
||||
info() { echo -e "\n\e[1;34m[INFO]\e[0m $*"; }
|
||||
warn() { echo -e "\n\e[1;33m[WARN]\e[0m $*"; }
|
||||
error() { echo -e "\n\e[1;31m[ERROR]\e[0m $*" >&2; exit 1; }
|
||||
|
||||
# ╭─────────────────────────────────────╮
|
||||
# │ OS + HARDWARE FINGERPRINT │
|
||||
# ╰─────────────────────────────────────╯
|
||||
OS_NAME=$(uname -s)
|
||||
KERNEL_VERSION=$(uname -r)
|
||||
ARCHITECTURE=$(uname -m)
|
||||
OS_PRETTY_NAME=$(grep PRETTY_NAME /etc/os-release 2>/dev/null | cut -d= -f2 | tr -d '"' || echo "Unknown")
|
||||
DOCKER_CHECK=$(grep -qE '/docker|/lxc' /proc/1/cgroup 2>/dev/null && echo "Yes" || echo "No")
|
||||
WSL_CHECK=$(grep -qi microsoft /proc/version 2>/dev/null && echo "Yes" || echo "No")
|
||||
VM_CHECK=$(command -v systemd-detect-virt >/dev/null && systemd-detect-virt || echo "Unknown")
|
||||
UPTIME=$(uptime -p 2>/dev/null || echo "Unknown")
|
||||
HOSTNAME=$(hostname)
|
||||
CURRENT_USER=$(whoami)
|
||||
TIMEZONE=$(date +%Z)
|
||||
LOCAL_IP=$(hostname -I | awk '{print $1}' || echo "Unknown")
|
||||
MAC_ADDRESS=$(ip link show | awk '/ether/ {print $2; exit}' || echo "Unknown")
|
||||
CPU_MODEL=$(grep -m1 "model name" /proc/cpuinfo | cut -d: -f2 | sed 's/^ //g' || echo "Unknown")
|
||||
TOTAL_RAM=$(awk '/MemTotal/ {printf "%.2f", $2/1024/1024}' /proc/meminfo 2>/dev/null || echo "Unknown")
|
||||
|
||||
# ╭─────────────────────────────────────╮
|
||||
# │ CHECK + INSTALL TOOLS │
|
||||
# ╰─────────────────────────────────────╯
|
||||
info "Checking prerequisites..."
|
||||
sudo apt update -qq
|
||||
sudo apt install -y git curl jq openssh-client || error "Dependency install failed"
|
||||
|
||||
# ╭─────────────────────────────────────╮
|
||||
# │ GIT IDENTITY SETUP │
|
||||
# ╰─────────────────────────────────────╯
|
||||
git config --global user.name "$FULL_NAME"
|
||||
git config --global user.email "$EMAIL"
|
||||
info "Git identity: $FULL_NAME <$EMAIL>"
|
||||
|
||||
# ╭─────────────────────────────────────╮
|
||||
# │ SSH KEYGEN + AGENT │
|
||||
# ╰─────────────────────────────────────╯
|
||||
if [ ! -f ~/.ssh/id_rsa ]; then
|
||||
info "Generating new SSH key..."
|
||||
ssh-keygen -t rsa -b 4096 -C "$EMAIL" -f ~/.ssh/id_rsa -N ""
|
||||
fi
|
||||
|
||||
eval "$(ssh-agent -s)"
|
||||
ssh-add ~/.ssh/id_rsa || error "Failed to add SSH key"
|
||||
ssh-keyscan -t rsa bitbucket.org >> ~/.ssh/known_hosts 2>/dev/null || true
|
||||
|
||||
# ╭─────────────────────────────────────╮
|
||||
# │ SSH AUTH VERIFICATION │
|
||||
# ╰─────────────────────────────────────╯
|
||||
info "Verifying SSH access to Bitbucket..."
|
||||
if ssh -T git@bitbucket.org 2>&1 | grep -q "authenticated"; then
|
||||
info "✓ SSH access to Bitbucket verified."
|
||||
else
|
||||
warn "❌ SSH key not authorized with Bitbucket."
|
||||
echo "→ Visit: https://bitbucket.org/account/settings/ssh-keys/"
|
||||
cat ~/.ssh/id_rsa.pub
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ╭─────────────────────────────────────╮
|
||||
# │ BITBUCKET APP PASSWORD SETUP │
|
||||
# ╰─────────────────────────────────────╯
|
||||
if [ ! -f "$APP_PASS_FILE" ]; then
|
||||
echo "🔐 Create a Bitbucket App Password (repo:admin + write + webhook)"
|
||||
echo "→ https://bitbucket.org/account/settings/app-passwords/"
|
||||
read -rsp "Enter Bitbucket App Password (input hidden): " APP_PASS
|
||||
echo "$APP_PASS" > "$APP_PASS_FILE"
|
||||
chmod 600 "$APP_PASS_FILE"
|
||||
fi
|
||||
APP_PASS=$(<"$APP_PASS_FILE")
|
||||
|
||||
# ╭─────────────────────────────────────╮
|
||||
# │ GIT INIT & COMMIT │
|
||||
# ╰─────────────────────────────────────╯
|
||||
if [ ! -d .git ]; then
|
||||
git init
|
||||
git add .
|
||||
git commit -m "Initial commit"
|
||||
fi
|
||||
|
||||
# ╭─────────────────────────────────────╮
|
||||
# │ CREATE REMOTE IF NOT EXISTS │
|
||||
# ╰─────────────────────────────────────╯
|
||||
REPO_EXISTS=$(curl -s -u "$BITBUCKET_USER:$APP_PASS" "$API_URL" | jq -r '.name // empty')
|
||||
if [ -z "$REPO_EXISTS" ]; then
|
||||
curl -s -u "$BITBUCKET_USER:$APP_PASS" -X POST "$API_URL" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"scm": "git", "is_private": false}'
|
||||
fi
|
||||
|
||||
git remote remove "$REMOTE_NAME" 2>/dev/null || true
|
||||
git remote add "$REMOTE_NAME" "$SSH_REMOTE"
|
||||
|
||||
# ╭─────────────────────────────────────╮
|
||||
# │ WRITE METADATA MARKDOWN │
|
||||
# ╰─────────────────────────────────────╯
|
||||
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
|
||||
DEFAULT_BRANCH=$(git symbolic-ref --short HEAD)
|
||||
REPO_PATH=$(git rev-parse --show-toplevel)
|
||||
mkdir -p "$REPO_PATH/.gitfield" && MARKDOWN_FILE="$REPO_PATH/.gitfield/bitbucket.sigil.md"
|
||||
LATEST_SHA=$(git rev-parse HEAD)
|
||||
LAST_COMMIT_MSG=$(git log -1 --pretty=format:"%s")
|
||||
LAST_COMMIT_DATE=$(git log -1 --pretty=format:"%ad")
|
||||
LAST_COMMIT_AUTHOR=$(git log -1 --pretty=format:"%an <%ae>")
|
||||
TOTAL_COMMITS=$(git rev-list --count HEAD)
|
||||
TRACKED_FILES=$(git ls-files | wc -l)
|
||||
UNCOMMITTED=$(if ! git diff --quiet || ! git diff --cached --quiet; then echo "Yes"; else echo "No"; fi)
|
||||
LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "None")
|
||||
|
||||
cat > "$MARKDOWN_FILE" <<EOF
|
||||
# 🔗 Bitbucket Repository Link
|
||||
|
||||
- **Repo Name**: \`$REPO_NAME\`
|
||||
- **Bitbucket Workspace**: \`$BITBUCKET_WORKSPACE\`
|
||||
- **Remote URL**: [$WEB_LINK]($WEB_LINK)
|
||||
- **Local Repo Path**: \`$REPO_PATH\`
|
||||
- **Remote Label**: \`$REMOTE_NAME\`
|
||||
- **Default Branch**: \`$DEFAULT_BRANCH\`
|
||||
- **This Commit Date**: \`$TIMESTAMP\`
|
||||
|
||||
---
|
||||
|
||||
## 📦 Commit Info
|
||||
|
||||
- **This Commit Timestamp**: \`$TIMESTAMP\`
|
||||
- **Last Commit SHA**: \`$LATEST_SHA\`
|
||||
- **Last Commit Message**: \`$LAST_COMMIT_MSG\`
|
||||
- **Last Commit Author**: \`$LAST_COMMIT_AUTHOR\`
|
||||
- **Last Commit Date**: \`$LAST_COMMIT_DATE\`
|
||||
- **This Commit URL**: [$WEB_LINK/commits/$LATEST_SHA]($WEB_LINK/commits/$LATEST_SHA)
|
||||
|
||||
---
|
||||
|
||||
## 📊 Repo Status
|
||||
|
||||
- **Total Commits**: \`$TOTAL_COMMITS\`
|
||||
- **Tracked Files**: \`$TRACKED_FILES\`
|
||||
- **Uncommitted Changes**: \`$UNCOMMITTED\`
|
||||
- **Latest Tag**: \`$LATEST_TAG\`
|
||||
|
||||
---
|
||||
|
||||
## 🧭 Environment
|
||||
|
||||
- **Host Machine**: \`$HOSTNAME\`
|
||||
- **Current User**: \`$CURRENT_USER\`
|
||||
- **Time Zone**: \`$TIMEZONE\`
|
||||
- **Script Version**: \`v$SCRIPT_VERSION\`
|
||||
|
||||
---
|
||||
|
||||
## 🧬 Hardware & OS Fingerprint
|
||||
|
||||
- **OS Name**: \`$OS_NAME\`
|
||||
- **OS Version**: \`$OS_PRETTY_NAME\`
|
||||
- **Kernel Version**: \`$KERNEL_VERSION\`
|
||||
- **Architecture**: \`$ARCHITECTURE\`
|
||||
- **CPU Model**: \`$CPU_MODEL\`
|
||||
- **Total RAM (GB)**: \`$TOTAL_RAM\`
|
||||
- **MAC Address**: \`$MAC_ADDRESS\`
|
||||
- **Local IP**: \`$LOCAL_IP\`
|
||||
- **Running in Docker**: \`$DOCKER_CHECK\`
|
||||
- **Running in WSL**: \`$WSL_CHECK\`
|
||||
- **Virtual Machine**: \`$VM_CHECK\`
|
||||
- **System Uptime**: \`$UPTIME\`
|
||||
|
||||
---
|
||||
|
||||
_Auto-generated by \`gitfield-bitbucket\` push script._
|
||||
EOF
|
||||
|
||||
git add "$MARKDOWN_FILE"
|
||||
git commit -m "Bitbucket metadata link commit at $TIMESTAMP — $WEB_LINK/commits/$LATEST_SHA" || warn "No changes to commit for $MARKDOWN_FILE"
|
||||
|
||||
git push -u "$REMOTE_NAME" "$DEFAULT_BRANCH"
|
||||
echo -e "\n🔗 View in browser: $WEB_LINK\n"
|
193
gitfield-github
Executable file
193
gitfield-github
Executable file
|
@ -0,0 +1,193 @@
|
|||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
IFS=$'\n\t'
|
||||
|
||||
# ╭─────────────────────────────────────╮
|
||||
# │ CONFIGURATION │
|
||||
# ╰─────────────────────────────────────╯
|
||||
GIT_REMOTE_NAME="github"
|
||||
REPO_NAME=$(basename "$(pwd)")
|
||||
DEFAULT_NAME="Mark Randall Havens"
|
||||
DEFAULT_EMAIL="mark.r.havens@gmail.com"
|
||||
SCRIPT_VERSION="1.0"
|
||||
|
||||
# ╭─────────────────────────────────────╮
|
||||
# │ LOGGING UTILS │
|
||||
# ╰─────────────────────────────────────╯
|
||||
info() { echo -e "\e[1;34m[INFO]\e[0m $*"; }
|
||||
warn() { echo -e "\e[1;33m[WARN]\e[0m $*"; }
|
||||
error() { echo -e "\e[1;31m[ERROR]\e[0m $*" >&2; exit 1; }
|
||||
|
||||
# ╭─────────────────────────────────────╮
|
||||
# │ TOOLCHAIN SETUP │
|
||||
# ╰─────────────────────────────────────╯
|
||||
info "Checking for required tools..."
|
||||
sudo apt update -qq
|
||||
sudo apt install -y git curl jq openssh-client lsb-release || error "Tool install failed"
|
||||
|
||||
if ! command -v gh &>/dev/null; then
|
||||
info "Installing GitHub CLI..."
|
||||
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg
|
||||
sudo chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg
|
||||
echo "deb [arch=$(dpkg --print-architecture)] signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg https://cli.github.com/packages stable main" | \
|
||||
sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null
|
||||
sudo apt update && sudo apt install gh -y || error "GitHub CLI install failed"
|
||||
fi
|
||||
|
||||
# ╭─────────────────────────────────────╮
|
||||
# │ AUTH + IDENTITY │
|
||||
# ╰─────────────────────────────────────╯
|
||||
if ! gh auth status &>/dev/null; then
|
||||
gh auth login || error "GitHub authentication failed"
|
||||
fi
|
||||
|
||||
git config --global user.name "${DEFAULT_NAME}"
|
||||
git config --global user.email "${DEFAULT_EMAIL}"
|
||||
|
||||
# ╭─────────────────────────────────────╮
|
||||
# │ SSH + GIT INIT │
|
||||
# ╰─────────────────────────────────────╯
|
||||
if [ ! -f "$HOME/.ssh/id_ed25519" ]; then
|
||||
ssh-keygen -t ed25519 -C "$DEFAULT_EMAIL" -f "$HOME/.ssh/id_ed25519" -N ""
|
||||
eval "$(ssh-agent -s)"
|
||||
ssh-add "$HOME/.ssh/id_ed25519"
|
||||
gh ssh-key add "$HOME/.ssh/id_ed25519.pub" --title "$(hostname)" || warn "Manual add may be needed"
|
||||
fi
|
||||
|
||||
if [ ! -d .git ]; then
|
||||
git init
|
||||
git add .
|
||||
git commit -m "Initial commit"
|
||||
fi
|
||||
|
||||
# ╭─────────────────────────────────────╮
|
||||
# │ GITHUB REPO CONFIGURATION │
|
||||
# ╰─────────────────────────────────────╯
|
||||
USERNAME=$(gh api user | jq -r .login)
|
||||
SSH_REMOTE_URL="git@github.com:$USERNAME/$REPO_NAME.git"
|
||||
WEB_LINK="https://github.com/$USERNAME/$REPO_NAME"
|
||||
|
||||
if ! git remote get-url "$GIT_REMOTE_NAME" &>/dev/null; then
|
||||
if gh repo view "$USERNAME/$REPO_NAME" &>/dev/null; then
|
||||
git remote add "$GIT_REMOTE_NAME" "$SSH_REMOTE_URL"
|
||||
else
|
||||
gh repo create "$REPO_NAME" --public --source=. --remote="$GIT_REMOTE_NAME" --push || error "Failed to create repo"
|
||||
fi
|
||||
else
|
||||
git remote set-url "$GIT_REMOTE_NAME" "$SSH_REMOTE_URL"
|
||||
fi
|
||||
|
||||
# ╭─────────────────────────────────────╮
|
||||
# │ GIT METADATA SNAPSHOT │
|
||||
# ╰─────────────────────────────────────╯
|
||||
TIMESTAMP="$(date '+%Y-%m-%d %H:%M:%S')"
|
||||
DEFAULT_BRANCH="$(git symbolic-ref --short HEAD)"
|
||||
REPO_PATH="$(git rev-parse --show-toplevel)"
|
||||
mkdir -p "$REPO_PATH/.gitfield" && MARKDOWN_FILE="$REPO_PATH/.gitfield/github.sigil.md"
|
||||
LATEST_SHA=$(git rev-parse HEAD)
|
||||
LAST_COMMIT_MSG=$(git log -1 --pretty=format:"%s")
|
||||
LAST_COMMIT_DATE=$(git log -1 --pretty=format:"%ad")
|
||||
LAST_COMMIT_AUTHOR=$(git log -1 --pretty=format:"%an <%ae>")
|
||||
TOTAL_COMMITS=$(git rev-list --count HEAD)
|
||||
TRACKED_FILES=$(git ls-files | wc -l)
|
||||
UNCOMMITTED=$(if ! git diff --quiet || ! git diff --cached --quiet; then echo "Yes"; else echo "No"; fi)
|
||||
LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "None")
|
||||
HOSTNAME=$(hostname)
|
||||
CURRENT_USER=$(whoami)
|
||||
TIMEZONE=$(date +%Z)
|
||||
|
||||
# ╭─────────────────────────────────────╮
|
||||
# │ HARDWARE + OS FINGERPRINT BLOCK │
|
||||
# ╰─────────────────────────────────────╯
|
||||
OS_NAME=$(uname -s)
|
||||
KERNEL_VERSION=$(uname -r)
|
||||
ARCHITECTURE=$(uname -m)
|
||||
OS_PRETTY_NAME=$(grep PRETTY_NAME /etc/os-release 2>/dev/null | cut -d= -f2 | tr -d '"') || OS_PRETTY_NAME="Unknown"
|
||||
DOCKER_CHECK=$(grep -qE '/docker|/lxc' /proc/1/cgroup 2>/dev/null && echo "Yes" || echo "No")
|
||||
WSL_CHECK=$(grep -qi microsoft /proc/version 2>/dev/null && echo "Yes" || echo "No")
|
||||
VM_CHECK=$(systemd-detect-virt 2>/dev/null || echo "Unknown")
|
||||
UPTIME=$(uptime -p 2>/dev/null || echo "Unknown")
|
||||
MAC_ADDR=$(ip link | awk '/ether/ {print $2}' | head -n 1)
|
||||
LOCAL_IP=$(hostname -I | awk '{print $1}')
|
||||
CPU_MODEL=$(grep -m1 'model name' /proc/cpuinfo | cut -d: -f2 | sed 's/^ //')
|
||||
RAM_GB=$(awk '/MemTotal/ {printf "%.2f", $2/1024/1024}' /proc/meminfo)
|
||||
|
||||
# ╭─────────────────────────────────────╮
|
||||
# │ WRITE RICH MARKDOWN ARTIFACT │
|
||||
# ╰─────────────────────────────────────╯
|
||||
cat > "$MARKDOWN_FILE" <<EOF
|
||||
# 🔗 GitHub Repository Link
|
||||
|
||||
- **Repo Name**: \`$REPO_NAME\`
|
||||
- **GitHub User**: \`$USERNAME\`
|
||||
- **Remote URL**: [$WEB_LINK]($WEB_LINK)
|
||||
- **Local Repo Path**: \`$REPO_PATH\`
|
||||
- **Remote Label**: \`$GIT_REMOTE_NAME\`
|
||||
- **Default Branch**: \`$DEFAULT_BRANCH\`
|
||||
- **This Commit Date**: \`$TIMESTAMP\`
|
||||
|
||||
---
|
||||
|
||||
## 📦 Commit Info
|
||||
|
||||
- **This Commit Timestamp**: \`$TIMESTAMP\`
|
||||
- **Last Commit SHA**: \`$LATEST_SHA\`
|
||||
- **Last Commit Message**: \`$LAST_COMMIT_MSG\`
|
||||
- **Last Commit Author**: \`$LAST_COMMIT_AUTHOR\`
|
||||
- **Last Commit Date**: \`$LAST_COMMIT_DATE\`
|
||||
- **This Commit URL**: [$WEB_LINK/commit/$LATEST_SHA]($WEB_LINK/commit/$LATEST_SHA)
|
||||
|
||||
---
|
||||
|
||||
## 📊 Repo Status
|
||||
|
||||
- **Total Commits**: \`$TOTAL_COMMITS\`
|
||||
- **Tracked Files**: \`$TRACKED_FILES\`
|
||||
- **Uncommitted Changes**: \`$UNCOMMITTED\`
|
||||
- **Latest Tag**: \`$LATEST_TAG\`
|
||||
|
||||
---
|
||||
|
||||
## 🧭 Environment
|
||||
|
||||
- **Host Machine**: \`$HOSTNAME\`
|
||||
- **Current User**: \`$CURRENT_USER\`
|
||||
- **Time Zone**: \`$TIMEZONE\`
|
||||
- **Script Version**: \`v$SCRIPT_VERSION\`
|
||||
|
||||
---
|
||||
|
||||
## 🧬 Hardware & OS Fingerprint
|
||||
|
||||
- **OS Name**: \`$OS_NAME\`
|
||||
- **OS Version**: \`$OS_PRETTY_NAME\`
|
||||
- **Kernel Version**: \`$KERNEL_VERSION\`
|
||||
- **Architecture**: \`$ARCHITECTURE\`
|
||||
- **Running in Docker**: \`$DOCKER_CHECK\`
|
||||
- **Running in WSL**: \`$WSL_CHECK\`
|
||||
- **Virtual Machine**: \`$VM_CHECK\`
|
||||
- **System Uptime**: \`$UPTIME\`
|
||||
- **MAC Address**: \`$MAC_ADDR\`
|
||||
- **Local IP**: \`$LOCAL_IP\`
|
||||
- **CPU Model**: \`$CPU_MODEL\`
|
||||
- **Total RAM (GB)**: \`$RAM_GB\`
|
||||
|
||||
---
|
||||
|
||||
_Auto-generated by \`gitfield-github\` push script._
|
||||
EOF
|
||||
|
||||
# ╭─────────────────────────────────────╮
|
||||
# │ COMMIT & PUSH MARKDOWN FILE │
|
||||
# ╰─────────────────────────────────────╯
|
||||
git add "$MARKDOWN_FILE"
|
||||
git commit -m "GitHub metadata link commit at $TIMESTAMP — $WEB_LINK/commit/$LATEST_SHA" || warn "No changes to commit for $MARKDOWN_FILE"
|
||||
|
||||
if ! git config --get branch."$DEFAULT_BRANCH".remote &>/dev/null; then
|
||||
git push -u "$GIT_REMOTE_NAME" "$DEFAULT_BRANCH"
|
||||
else
|
||||
git push "$GIT_REMOTE_NAME" "$DEFAULT_BRANCH"
|
||||
fi
|
||||
|
||||
info "✅ GitHub push complete."
|
||||
echo -e "\n🔗 View in browser: $WEB_LINK\n"
|
242
gitfield-gitlab
Executable file
242
gitfield-gitlab
Executable file
|
@ -0,0 +1,242 @@
|
|||
#!/bin/bash
|
||||
IFS=$'\n\t'
|
||||
|
||||
# Configuration
|
||||
GIT_REMOTE_NAME="gitlab"
|
||||
REPO_NAME=$(basename "$(pwd)") || REPO_NAME="Unknown"
|
||||
DEFAULT_NAME="Mark Randall Havens"
|
||||
DEFAULT_EMAIL="mark.r.havens@gmail.com"
|
||||
GITLAB_WEB="https://gitlab.com"
|
||||
GITLAB_API="$GITLAB_WEB/api/v4"
|
||||
GITLAB_SSH="git@gitlab.com"
|
||||
TOKEN_FILE="$HOME/.gitfield_token"
|
||||
SCRIPT_VERSION="1.0"
|
||||
MARKDOWN_FILE="$(git rev-parse --show-toplevel)/.gitfield/gitlab.sigil.md" && mkdir -p "$(dirname "$MARKDOWN_FILE")"
|
||||
|
||||
info() { echo -e "\e[1;34m[INFO]\e[0m $*"; }
|
||||
warn() { echo -e "\e[1;33m[WARN]\e[0m $*"; }
|
||||
error() { echo -e "\e[1;31m[ERROR]\e[0m $*" >&2; exit 1; }
|
||||
|
||||
# Function to generate markdown file
|
||||
generate_markdown() {
|
||||
info "Generating markdown file: $MARKDOWN_FILE"
|
||||
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S' 2>/dev/null || echo "Unknown")
|
||||
DEFAULT_BRANCH=$(git symbolic-ref --short HEAD 2>/dev/null || echo "Unknown")
|
||||
REPO_PATH=$(git rev-parse --show-toplevel)
|
||||
LATEST_SHA=$(git rev-parse HEAD 2>/dev/null || echo "Unknown")
|
||||
LAST_COMMIT_MSG=$(git log -1 --pretty=format:"%s" 2>/dev/null || echo "Unknown")
|
||||
LAST_COMMIT_DATE=$(git log -1 --pretty=format:"%ad" 2>/dev/null || echo "Unknown")
|
||||
LAST_COMMIT_AUTHOR=$(git log -1 --pretty=format:"%an <%ae>" 2>/dev/null || echo "Unknown")
|
||||
TOTAL_COMMITS=$(git rev-list --count HEAD 2>/dev/null || echo "Unknown")
|
||||
TRACKED_FILES=$(git ls-files 2>/dev/null | wc -l 2>/dev/null || echo "Unknown")
|
||||
UNCOMMITTED=$(if ! git diff --quiet 2>/dev/null || ! git diff --cached --quiet 2>/dev/null; then echo "Yes"; else echo "No"; fi)
|
||||
LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "None")
|
||||
HOSTNAME=$(hostname 2>/dev/null || echo "Unknown")
|
||||
CURRENT_USER=$(whoami 2>/dev/null || echo "Unknown")
|
||||
TIMEZONE=$(date +%Z 2>/dev/null || echo "Unknown")
|
||||
OS_NAME=$(uname -s 2>/dev/null || echo "Unknown")
|
||||
KERNEL_VERSION=$(uname -r 2>/dev/null || echo "Unknown")
|
||||
ARCHITECTURE=$(uname -m 2>/dev/null || echo "Unknown")
|
||||
OS_PRETTY_NAME=$(grep PRETTY_NAME /etc/os-release 2>/dev/null | cut -d= -f2 | tr -d '"' || echo "Unknown")
|
||||
DOCKER_CHECK=$(grep -qE '/docker|/lxc' /proc/1/cgroup 2>/dev/null && echo "Yes" || echo "No")
|
||||
WSL_CHECK=$(grep -qi microsoft /proc/version 2>/dev/null && echo "Yes" || echo "No")
|
||||
VM_CHECK=$(systemd-detect-virt 2>/dev/null || echo "Unknown")
|
||||
UPTIME=$(uptime -p 2>/dev/null || echo "Unknown")
|
||||
MAC_ADDR=$(ip link 2>/dev/null | awk '/ether/ {print $2}' | head -n 1 2>/dev/null || echo "Unknown")
|
||||
LOCAL_IP=$(hostname -I 2>/dev/null | awk '{print $1}' 2>/dev/null || echo "Unknown")
|
||||
CPU_MODEL=$(grep -m1 'model name' /proc/cpuinfo 2>/dev/null | cut -d: -f2 | sed 's/^ //' 2>/dev/null || echo "Unknown")
|
||||
RAM_GB=$(awk '/MemTotal/ {printf "%.2f", $2/1024/1024}' /proc/meminfo 2>/dev/null || echo "Unknown")
|
||||
WEB_LINK="$GITLAB_WEB/$USERNAME/$REPO_NAME"
|
||||
|
||||
cat > "$MARKDOWN_FILE" <<EOF
|
||||
# 🔗 GitLab Repository Link
|
||||
|
||||
- **Repo Name**: \`$REPO_NAME\`
|
||||
- **GitLab User**: \`$USERNAME\`
|
||||
- **Remote URL**: [$WEB_LINK]($WEB_LINK)
|
||||
- **Local Repo Path**: \`$REPO_PATH\`
|
||||
- **Remote Label**: \`$GIT_REMOTE_NAME\`
|
||||
- **Default Branch**: \`$DEFAULT_BRANCH\`
|
||||
- **Repo Created**: \`$TIMESTAMP\`
|
||||
|
||||
---
|
||||
|
||||
## 📦 Commit Info
|
||||
|
||||
- **This Commit Timestamp**: \`$TIMESTAMP\`
|
||||
- **This Commit SHA**: \`$LATEST_SHA\`
|
||||
- **Last Commit Message**: \`$LAST_COMMIT_MSG\`
|
||||
- **Last Commit Author**: \`$LAST_COMMIT_AUTHOR\`
|
||||
- **Last Commit Date**: \`$LAST_COMMIT_DATE\`
|
||||
- **This Commit URL**: [$WEB_LINK/-/commit/$LATEST_SHA]($WEB_LINK/-/commit/$LATEST_SHA)
|
||||
|
||||
---
|
||||
|
||||
## 📊 Repo Status
|
||||
|
||||
- **Total Commits**: \`$TOTAL_COMMITS\`
|
||||
- **Tracked Files**: \`$TRACKED_FILES\`
|
||||
- **Uncommitted Changes**: \`$UNCOMMITTED\`
|
||||
- **Latest Tag**: \`$LATEST_TAG\`
|
||||
|
||||
---
|
||||
|
||||
## 🧽 Environment
|
||||
|
||||
- **Host Machine**: \`$HOSTNAME\`
|
||||
- **Current User**: \`$CURRENT_USER\`
|
||||
- **Time Zone**: \`$TIMEZONE\`
|
||||
- **Script Version**: \`v$SCRIPT_VERSION\`
|
||||
|
||||
---
|
||||
|
||||
## 🧬 Hardware & OS Fingerprint
|
||||
|
||||
- **OS Name**: \`$OS_NAME\`
|
||||
- **OS Version**: \`$OS_PRETTY_NAME\`
|
||||
- **Kernel Version**: \`$KERNEL_VERSION\`
|
||||
- **Architecture**: \`$ARCHITECTURE\`
|
||||
- **Running in Docker**: \`$DOCKER_CHECK\`
|
||||
- **Running in WSL**: \`$WSL_CHECK\`
|
||||
- **Virtual Machine**: \`$VM_CHECK\`
|
||||
- **System Uptime**: \`$UPTIME\`
|
||||
- **MAC Address**: \`$MAC_ADDR\`
|
||||
- **Local IP**: \`$LOCAL_IP\`
|
||||
- **CPU Model**: \`$CPU_MODEL\`
|
||||
- **Total RAM (GB)**: \`$RAM_GB\`
|
||||
|
||||
---
|
||||
|
||||
_Auto-generated by \`gitfield-gitlab\` push script._
|
||||
EOF
|
||||
}
|
||||
|
||||
# Main script
|
||||
set -euo pipefail
|
||||
|
||||
# Token Handling
|
||||
RESET_TOKEN=false
|
||||
if [[ "${1:-}" == "--reset-token" ]]; then
|
||||
RESET_TOKEN=true
|
||||
rm -f "$TOKEN_FILE" 2>/dev/null || warn "Failed to remove token file"
|
||||
info "Token reset requested."
|
||||
fi
|
||||
|
||||
if [ -f "$TOKEN_FILE" ] && [ "$RESET_TOKEN" = false ]; then
|
||||
TOKEN=$(cat "$TOKEN_FILE" 2>/dev/null || error "Failed to read token file")
|
||||
info "Using cached token from $TOKEN_FILE"
|
||||
else
|
||||
echo
|
||||
echo "🔐 Paste your GitLab Personal Access Token (scopes: api, read_user, write_repository, write_ssh_key)"
|
||||
echo "→ Generate at: $GITLAB_WEB/-/user_settings/personal_access_tokens"
|
||||
read -rp "🔑 Token: " TOKEN
|
||||
echo "$TOKEN" > "$TOKEN_FILE" 2>/dev/null || warn "Failed to save token file"
|
||||
chmod 600 "$TOKEN_FILE" 2>/dev/null || warn "Failed to set token file permissions"
|
||||
info "Token saved for future use at $TOKEN_FILE"
|
||||
fi
|
||||
|
||||
# Install Dependencies
|
||||
sudo apt update -qq 2>/dev/null || warn "apt update failed, continuing..."
|
||||
sudo apt install -y git curl jq openssh-client lsb-release 2>/dev/null || warn "Tool install failed, continuing..."
|
||||
|
||||
# Identity
|
||||
git config --global user.name "$DEFAULT_NAME" 2>/dev/null || warn "Failed to set git user name"
|
||||
git config --global user.email "$DEFAULT_EMAIL" 2>/dev/null || warn "Failed to set git user email"
|
||||
info "Git identity set to: $DEFAULT_NAME <$DEFAULT_EMAIL>"
|
||||
|
||||
# Git Initialization
|
||||
if [ ! -d .git ]; then
|
||||
git init 2>/dev/null || warn "Git init failed, continuing..."
|
||||
git add . 2>/dev/null || warn "Nothing to add"
|
||||
git commit -m "Initial commit" 2>/dev/null || warn "Nothing to commit"
|
||||
fi
|
||||
|
||||
if ! git rev-parse HEAD &>/dev/null; then
|
||||
git add . 2>/dev/null && git commit -m "Initial commit" 2>/dev/null || warn "Nothing to commit"
|
||||
fi
|
||||
|
||||
# SSH Setup
|
||||
if [ ! -f ~/.ssh/id_rsa ]; then
|
||||
ssh-keygen -t rsa -b 4096 -C "$DEFAULT_EMAIL" -f ~/.ssh/id_rsa -N "" 2>/dev/null || error "SSH keygen failed"
|
||||
fi
|
||||
|
||||
eval "$(ssh-agent -s 2>/dev/null)" || warn "Failed to start ssh-agent, continuing..."
|
||||
ssh-add ~/.ssh/id_rsa 2>/dev/null || error "Failed to add SSH key"
|
||||
|
||||
# Fetch GitLab Username
|
||||
USERNAME=$(curl -s --header "PRIVATE-TOKEN: $TOKEN" "$GITLAB_API/user" | jq -r '.username' 2>/dev/null) || error "Invalid token"
|
||||
info "GitLab username: $USERNAME"
|
||||
|
||||
# SSH Key Upload to GitLab
|
||||
SSH_TEST_OUTPUT=$(ssh -T "$GITLAB_SSH" 2>&1)
|
||||
if ! echo "$SSH_TEST_OUTPUT" | grep -q "Welcome"; then
|
||||
warn "SSH test failed, attempting to upload SSH key. Output: $SSH_TEST_OUTPUT"
|
||||
PUBKEY=$(cat ~/.ssh/id_rsa.pub 2>/dev/null || warn "Failed to read SSH public key, continuing...")
|
||||
TITLE="AutoKey-$(hostname)-$(date +%s 2>/dev/null || echo 'unknown')"
|
||||
CURL_OUTPUT=$(curl -s --fail -X POST "$GITLAB_API/user/keys" \
|
||||
-H "PRIVATE-TOKEN: $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"title\": \"$TITLE\", \"key\": \"$PUBKEY\"}" 2>&1)
|
||||
if [[ $? -ne 0 ]]; then
|
||||
warn "SSH key upload failed: $CURL_OUTPUT"
|
||||
else
|
||||
info "SSH key uploaded successfully."
|
||||
sleep 2
|
||||
SSH_TEST_OUTPUT=$(ssh -T "$GITLAB_SSH" 2>&1)
|
||||
if ! echo "$SSH_TEST_OUTPUT" | grep -q "Welcome"; then
|
||||
warn "SSH test still failing after key upload. Output: $SSH_TEST_OUTPUT"
|
||||
else
|
||||
info "SSH test passed after key upload."
|
||||
fi
|
||||
fi
|
||||
else
|
||||
info "SSH test passed: $SSH_TEST_OUTPUT"
|
||||
fi
|
||||
|
||||
# Set Up Remote Repository (non-critical, allow failures)
|
||||
set +e
|
||||
REMOTE_URL="$GITLAB_SSH:$USERNAME/$REPO_NAME.git"
|
||||
info "Checking if remote '$GIT_REMOTE_NAME' exists..."
|
||||
REMOTE_EXISTS=$(git remote get-url "$GIT_REMOTE_NAME" 2>&1)
|
||||
REMOTE_EXIT_CODE=$?
|
||||
info "git remote get-url output: $REMOTE_EXISTS"
|
||||
info "git remote get-url exit code: $REMOTE_EXIT_CODE"
|
||||
|
||||
if [[ $REMOTE_EXIT_CODE -ne 0 ]]; then
|
||||
info "Remote '$GIT_REMOTE_NAME' not found, setting up..."
|
||||
CURL_OUTPUT=$(curl -s --fail -X POST "$GITLAB_API/projects" \
|
||||
-H "PRIVATE-TOKEN: $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"name\": \"$REPO_NAME\", \"visibility\": \"public\"}" 2>&1)
|
||||
if [[ $? -ne 0 ]]; then
|
||||
warn "Failed to create GitLab project: $CURL_OUTPUT"
|
||||
PROJECT_EXISTS=$(curl -s --header "PRIVATE-TOKEN: $TOKEN" "$GITLAB_API/projects?search=$REPO_NAME" | jq -r '.[] | select(.name == "'"$REPO_NAME"'") | .id' 2>&1)
|
||||
if [[ $? -ne 0 || -z "$PROJECT_EXISTS" ]]; then
|
||||
warn "Project creation failed and project does not exist: $PROJECT_EXISTS"
|
||||
info "Proceeding with remote URL anyway: $REMOTE_URL"
|
||||
else
|
||||
info "Project already exists on GitLab."
|
||||
fi
|
||||
else
|
||||
info "GitLab project created successfully."
|
||||
fi
|
||||
git remote add "$GIT_REMOTE_NAME" "$REMOTE_URL" 2>/dev/null || warn "Failed to add remote, but continuing..."
|
||||
info "Remote set to: $REMOTE_URL"
|
||||
else
|
||||
info "Remote already configured: $REMOTE_EXISTS"
|
||||
fi
|
||||
set -e
|
||||
|
||||
# Generate markdown file (always run this step)
|
||||
generate_markdown
|
||||
|
||||
# Commit and Push (non-critical, allow failures)
|
||||
set +e
|
||||
info "Committing markdown file..."
|
||||
git add "$MARKDOWN_FILE" 2>/dev/null || warn "Failed to add markdown file"
|
||||
git commit -m "GitLab metadata link commit at $TIMESTAMP — $WEB_LINK/-/commit/$LATEST_SHA" 2>/dev/null || warn "No changes to commit"
|
||||
|
||||
info "Pushing to GitLab..."
|
||||
git push -u "$GIT_REMOTE_NAME" "$DEFAULT_BRANCH" 2>/dev/null || warn "Push to GitLab failed"
|
||||
echo -e "\n🔗 View in browser: $WEB_LINK\n"
|
||||
set -e
|
318
gitfield-radicle
Executable file
318
gitfield-radicle
Executable file
|
@ -0,0 +1,318 @@
|
|||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
IFS=$'\n\t'
|
||||
|
||||
# ╭───────────────────────────────╮
|
||||
# │ Config & Paths │
|
||||
# ╰───────────────────────────────╯
|
||||
PROJECT_NAME=$(basename "$(pwd)")
|
||||
DEFAULT_NAME="Mark Randall Havens"
|
||||
DEFAULT_EMAIL="mark.r.havens@gmail.com"
|
||||
SCRIPT_VERSION="1.0"
|
||||
|
||||
RAD_HOME="$HOME/.radicle"
|
||||
RAD_BIN="$RAD_HOME/bin/rad"
|
||||
RAD_PATH_LINE='export PATH="$HOME/.radicle/bin:$PATH"'
|
||||
PROFILE_FILE="$HOME/.bashrc"
|
||||
PUSH_STATE_FILE="$(git rev-parse --show-toplevel)/.gitfield/.radicle-push-state"
|
||||
MARKDOWN_FILE="$(git rev-parse --show-toplevel)/.gitfield/radicle.sigil.md"
|
||||
mkdir -p "$(dirname "$MARKDOWN_FILE")"
|
||||
PUBLIC_GATEWAY="https://app.radicle.xyz/nodes/ash.radicle.garden"
|
||||
|
||||
# ╭───────────────────────────────╮
|
||||
# │ Logging Utils │
|
||||
# ╰───────────────────────────────╯
|
||||
info() { echo -e "\e[1;34m[INFO]\e[0m $*"; }
|
||||
warn() { echo -e "\e[1;33m[WARN]\e[0m $*"; }
|
||||
error() { echo -e "\e[1;31m[ERROR]\e[0m $*" >&2; exit 1; }
|
||||
|
||||
# ╭───────────────────────────────╮
|
||||
# │ Git + Tools Precheck │
|
||||
# ╰───────────────────────────────╯
|
||||
info "Checking Git..."
|
||||
command -v git >/dev/null || {
|
||||
info "Installing Git..."
|
||||
sudo apt update && sudo apt install -y git || error "Failed to install Git"
|
||||
}
|
||||
info "Git version: $(git --version)"
|
||||
|
||||
NAME=$(git config --global user.name || true)
|
||||
EMAIL=$(git config --global user.email || true)
|
||||
[[ -z "$NAME" || -z "$EMAIL" ]] && {
|
||||
info "Setting Git identity..."
|
||||
git config --global user.name "$DEFAULT_NAME"
|
||||
git config --global user.email "$DEFAULT_EMAIL"
|
||||
}
|
||||
info "Git identity: $(git config --global user.name) <$(git config --global user.email)>"
|
||||
|
||||
# ╭───────────────────────────────╮
|
||||
# │ Radicle CLI Setup │
|
||||
# ╰───────────────────────────────╯
|
||||
if [ ! -x "$RAD_BIN" ]; then
|
||||
info "Installing Radicle CLI..."
|
||||
sudo apt install -y curl jq unzip || error "Missing dependencies"
|
||||
curl -sSf https://radicle.xyz/install | sh || error "Radicle install failed"
|
||||
fi
|
||||
export PATH="$HOME/.radicle/bin:$PATH"
|
||||
if ! grep -Fxq "$RAD_PATH_LINE" "$PROFILE_FILE"; then
|
||||
echo "$RAD_PATH_LINE" >> "$PROFILE_FILE"
|
||||
info "→ Added PATH to $PROFILE_FILE"
|
||||
warn "→ Run 'source $PROFILE_FILE' for persistent CLI access"
|
||||
fi
|
||||
command -v rad >/dev/null || error "Radicle CLI unavailable. Restart terminal or check PATH."
|
||||
info "Radicle CLI ready: $(rad --version)"
|
||||
|
||||
# ╭───────────────────────────────╮
|
||||
# │ Radicle Identity Check │
|
||||
# ╰───────────────────────────────╯
|
||||
info "Checking Radicle identity..."
|
||||
RAD_SELF_OUTPUT=$(rad self 2>&1 || true)
|
||||
if ! echo "$RAD_SELF_OUTPUT" | grep -q "DID"; then
|
||||
info "Creating new Radicle identity..."
|
||||
AUTH_OUTPUT=$(rad auth 2>&1) || error "Identity creation failed"
|
||||
info "$AUTH_OUTPUT"
|
||||
else
|
||||
info "Radicle identity already exists."
|
||||
fi
|
||||
|
||||
# ╭───────────────────────────────╮
|
||||
# │ Start Rad Node │
|
||||
# ╰───────────────────────────────╯
|
||||
if ! pgrep -f "rad node" >/dev/null; then
|
||||
info "Starting Radicle node..."
|
||||
rad node start || error "Failed to start Radicle node"
|
||||
else
|
||||
info "✓ Node is already running."
|
||||
fi
|
||||
info "Waiting for Radicle node to be ready..."
|
||||
for i in {1..30}; do
|
||||
if rad node status >/dev/null 2>&1; then
|
||||
info "Radicle node is ready."
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
rad node status >/dev/null 2>&1 || error "Radicle node failed to start after 30s."
|
||||
|
||||
# ╭───────────────────────────────╮
|
||||
# │ Git Repo Initialization │
|
||||
# ╰───────────────────────────────╯
|
||||
if [ ! -d .git ]; then
|
||||
info "Initializing Git repository..."
|
||||
git init
|
||||
git add . || warn "Nothing to add"
|
||||
git commit -m "Initial commit" || warn "Nothing to commit"
|
||||
else
|
||||
info "Git repo already initialized."
|
||||
fi
|
||||
|
||||
# ╭───────────────────────────────╮
|
||||
# │ Radicle Project Registration│
|
||||
# ╰───────────────────────────────╯
|
||||
if ! git remote | grep -q rad; then
|
||||
info "Registering Radicle project '$PROJECT_NAME'..."
|
||||
rad init --name "$PROJECT_NAME" --description "Radicle sovereign repo for $PROJECT_NAME" || error "Failed to initialize Radicle project"
|
||||
else
|
||||
info "Project '$PROJECT_NAME' already registered with Radicle."
|
||||
fi
|
||||
|
||||
# ╭───────────────────────────────╮
|
||||
# │ Extract Metadata │
|
||||
# ╰───────────────────────────────╯
|
||||
info "Extracting Radicle metadata..."
|
||||
# Extract Project ID
|
||||
PROJECT_ID=$(rad inspect | grep -o 'rad:[a-zA-Z0-9]\+' | cut -d':' -f2)
|
||||
info "→ Project ID from rad inspect: $PROJECT_ID"
|
||||
|
||||
# Extract Peer ID
|
||||
PEER_ID=""
|
||||
# Try rad self first
|
||||
if [[ -n "$RAD_SELF_OUTPUT" ]]; then
|
||||
PEER_ID=$(echo "$RAD_SELF_OUTPUT" | grep -o 'z6M[a-zA-Z0-9]\+' || true)
|
||||
info "→ Peer ID from rad self: $PEER_ID"
|
||||
fi
|
||||
# If rad self didn't provide it, try AUTH_OUTPUT if it exists
|
||||
if [[ -z "$PEER_ID" && -n "${AUTH_OUTPUT:-}" ]]; then
|
||||
PEER_ID=$(echo "$AUTH_OUTPUT" | grep -o 'z6M[a-zA-Z0-9]\+' || true)
|
||||
info "→ Peer ID from rad auth: $PEER_ID"
|
||||
fi
|
||||
# If still empty, try rad node status as a last resort
|
||||
if [[ -z "$PEER_ID" ]]; then
|
||||
NODE_STATUS=$(rad node status 2>&1)
|
||||
PEER_ID=$(echo "$NODE_STATUS" | grep -o 'z6M[a-zA-Z0-9]\+' || true)
|
||||
info "→ Peer ID from rad node status: $PEER_ID"
|
||||
fi
|
||||
|
||||
# Cross-check with Git remote
|
||||
RAD_REMOTE=$(git remote -v | grep rad | head -n1 | awk '{print $2}' || true)
|
||||
if [[ -n "$RAD_REMOTE" ]]; then
|
||||
REMOTE_PROJECT_ID=$(echo "$RAD_REMOTE" | cut -d'/' -f3)
|
||||
REMOTE_PEER_ID=$(echo "$RAD_REMOTE" | cut -d'/' -f4)
|
||||
info "→ Project ID from Git remote: $REMOTE_PROJECT_ID"
|
||||
info "→ Peer ID from Git remote: $REMOTE_PEER_ID"
|
||||
[[ "$PROJECT_ID" != "$REMOTE_PROJECT_ID" ]] && warn "Project ID mismatch: rad inspect ($PROJECT_ID) vs remote ($REMOTE_PROJECT_ID)"
|
||||
if [[ -z "$PEER_ID" && -n "$REMOTE_PEER_ID" ]]; then
|
||||
PEER_ID="$REMOTE_PEER_ID"
|
||||
info "→ Using Peer ID from Git remote as fallback: $PEER_ID"
|
||||
elif [[ -n "$REMOTE_PEER_ID" && "$PEER_ID" != "$REMOTE_PEER_ID" ]]; then
|
||||
warn "Peer ID mismatch: rad self ($PEER_ID) vs remote ($REMOTE_PEER_ID)"
|
||||
PEER_ID="$REMOTE_PEER_ID" # Prefer the remote Peer ID as it's part of the actual repo URL
|
||||
info "→ Using Peer ID from Git remote: $PEER_ID"
|
||||
fi
|
||||
PROJECT_ID="$REMOTE_PROJECT_ID" # Prefer the remote Project ID as it's the actual repo identifier
|
||||
fi
|
||||
|
||||
# Final validation
|
||||
if [[ -z "$PROJECT_ID" || -z "$PEER_ID" ]]; then
|
||||
error "Failed to determine Project ID ($PROJECT_ID) or Peer ID ($PEER_ID). Please check Radicle configuration."
|
||||
fi
|
||||
REPO_URN="rad://$PROJECT_ID"
|
||||
info "✓ Metadata extracted successfully: Project ID: $PROJECT_ID, Peer ID: $PEER_ID"
|
||||
|
||||
# ╭───────────────────────────────╮
|
||||
# │ Push Current Commit Logic │
|
||||
# ╰───────────────────────────────╯
|
||||
CURRENT_BRANCH=$(git symbolic-ref --short HEAD)
|
||||
CURRENT_COMMIT=$(git rev-parse HEAD)
|
||||
LAST_PUSHED_COMMIT=$(cat "$PUSH_STATE_FILE" 2>/dev/null || echo "none")
|
||||
|
||||
if [[ "$CURRENT_COMMIT" == "$LAST_PUSHED_COMMIT" ]]; then
|
||||
info "✓ Already pushed commit: $CURRENT_COMMIT"
|
||||
else
|
||||
info "Pushing commit '$CURRENT_COMMIT' on branch '$CURRENT_BRANCH'..."
|
||||
if git push rad "$CURRENT_BRANCH"; then
|
||||
echo "$CURRENT_COMMIT" > "$PUSH_STATE_FILE"
|
||||
info "✓ Pushed to Radicle successfully"
|
||||
else
|
||||
warn "Push failed — check 'rad sync status'"
|
||||
error "Push failed, cannot proceed."
|
||||
fi
|
||||
fi
|
||||
|
||||
# ╭─────────────────────────────────────╮
|
||||
# │ Git Metadata Snapshot │
|
||||
# ╰─────────────────────────────────────╯
|
||||
TIMESTAMP="$(date '+%Y-%m-%d %H:%M:%S')"
|
||||
DEFAULT_BRANCH="$CURRENT_BRANCH"
|
||||
REPO_PATH="$(git rev-parse --show-toplevel)"
|
||||
LATEST_SHA="$CURRENT_COMMIT"
|
||||
LAST_COMMIT_MSG=$(git log -1 --pretty=format:"%s")
|
||||
LAST_COMMIT_DATE=$(git log -1 --pretty=format:"%ad")
|
||||
LAST_COMMIT_AUTHOR=$(git log -1 --pretty=format:"%an <%ae>")
|
||||
TOTAL_COMMITS=$(git rev-list --count HEAD)
|
||||
TRACKED_FILES=$(git ls-files | wc -l)
|
||||
UNCOMMITTED=$(git diff --quiet && git diff --cached --quiet && echo "No" || echo "Yes")
|
||||
LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "None")
|
||||
HOSTNAME=$(hostname)
|
||||
CURRENT_USER=$(whoami)
|
||||
TIMEZONE=$(date +%Z)
|
||||
|
||||
# ╭─────────────────────────────────────╮
|
||||
# │ Hardware + OS Fingerprint Block │
|
||||
# ╰─────────────────────────────────────╯
|
||||
OS_NAME=$(uname -s)
|
||||
KERNEL_VERSION=$(uname -r)
|
||||
ARCHITECTURE=$(uname -m)
|
||||
OS_PRETTY_NAME=$(grep PRETTY_NAME /etc/os-release 2>/dev/null | cut -d= -f2 | tr -d '"' || echo "Unknown")
|
||||
DOCKER_CHECK=$(grep -qE '/docker|/lxc' /proc/1/cgroup 2>/dev/null && echo "Yes" || echo "No")
|
||||
WSL_CHECK=$(grep -qi microsoft /proc/version 2>/dev/null && echo "Yes" || echo "No")
|
||||
VM_CHECK=$(systemd-detect-virt 2>/dev/null || echo "Unknown")
|
||||
UPTIME=$(uptime -p 2>/dev/null || echo "Unknown")
|
||||
MAC_ADDR=$(ip link | awk '/ether/ {print $2}' | head -n 1 || echo "Unknown")
|
||||
LOCAL_IP=$(hostname -I | awk '{print $1}' || echo "Unknown")
|
||||
CPU_MODEL=$(grep -m1 'model name' /proc/cpuinfo | cut -d: -f2 | sed 's/^ //' || echo "Unknown")
|
||||
RAM_GB=$(awk '/MemTotal/ {printf "%.2f", $2/1024/1024}' /proc/meminfo || echo "Unknown")
|
||||
|
||||
# ╭─────────────────────────────────────╮
|
||||
# │ Write Rich Markdown Artifact │
|
||||
# ╰─────────────────────────────────────╯
|
||||
PUBLIC_GATEWAY_URL="$PUBLIC_GATEWAY/rad:$PROJECT_ID/tree/$LATEST_SHA"
|
||||
cat > "$MARKDOWN_FILE" <<EOF
|
||||
# 🔗 Radicle Repository Link
|
||||
|
||||
- **Project Name**: \`$PROJECT_NAME\`
|
||||
- **Radicle URN**: \`$REPO_URN\`
|
||||
- **Public Gateway**: [$PUBLIC_GATEWAY_URL]($PUBLIC_GATEWAY_URL)
|
||||
- **Local Repo Path**: \`$REPO_PATH\`
|
||||
- **Default Branch**: \`$DEFAULT_BRANCH\`
|
||||
- **Repo Created**: \`$TIMESTAMP\`
|
||||
|
||||
---
|
||||
|
||||
## 📦 Commit Info
|
||||
|
||||
- **This Commit Timestamp**: \`$TIMESTAMP\`
|
||||
- **Last Commit SHA**: \`$LATEST_SHA\`
|
||||
- **Last Commit Message**: \`$LAST_COMMIT_MSG\`
|
||||
- **Commit Author**: \`$LAST_COMMIT_AUTHOR\`
|
||||
- **Commit Date**: \`$LAST_COMMIT_DATE\`
|
||||
- **This Commit URL**: [$PUBLIC_GATEWAY_URL]($PUBLIC_GATEWAY_URL)
|
||||
|
||||
---
|
||||
|
||||
## 📊 Repo Status
|
||||
|
||||
- **Total Commits**: \`$TOTAL_COMMITS\`
|
||||
- **Tracked Files**: \`$TRACKED_FILES\`
|
||||
- **Uncommitted Changes**: \`$UNCOMMITTED\`
|
||||
- **Latest Tag**: \`$LATEST_TAG\`
|
||||
|
||||
---
|
||||
|
||||
## 🧭 Environment
|
||||
|
||||
- **Host Machine**: \`$HOSTNAME\`
|
||||
- **Current User**: \`$CURRENT_USER\`
|
||||
- **Time Zone**: \`$TIMEZONE\`
|
||||
- **Script Version**: \`v$SCRIPT_VERSION\`
|
||||
|
||||
---
|
||||
|
||||
## 🧬 Hardware & OS Fingerprint
|
||||
|
||||
- **OS Name**: \`$OS_NAME\`
|
||||
- **OS Version**: \`$OS_PRETTY_NAME\`
|
||||
- **Kernel Version**: \`$KERNEL_VERSION\`
|
||||
- **Architecture**: \`$ARCHITECTURE\`
|
||||
- **Running in Docker**: \`$DOCKER_CHECK\`
|
||||
- **Running in WSL**: \`$WSL_CHECK\`
|
||||
- **Virtual Machine**: \`$VM_CHECK\`
|
||||
- **System Uptime**: \`$UPTIME\`
|
||||
- **MAC Address**: \`$MAC_ADDR\`
|
||||
- **Local IP**: \`$LOCAL_IP\`
|
||||
- **CPU Model**: \`$CPU_MODEL\`
|
||||
- **Total RAM (GB)**: \`$RAM_GB\`
|
||||
|
||||
---
|
||||
|
||||
## 🌱 Radicle-Specific Metadata
|
||||
|
||||
- **Project ID**: \`$PROJECT_ID\`
|
||||
- **Peer ID**: \`$PEER_ID\`
|
||||
- **Public Gateway Base**: \`$PUBLIC_GATEWAY\`
|
||||
|
||||
---
|
||||
|
||||
_Auto-generated by \`gitfield-radicle\` push script._
|
||||
EOF
|
||||
|
||||
# ╭───────────────────────────────╮
|
||||
# │ Final Output Block │
|
||||
# ╰───────────────────────────────╯
|
||||
info "✓ Project ID: $PROJECT_ID"
|
||||
info "→ Peer ID: $PEER_ID (Share to connect)"
|
||||
info "🔗 View in browser: $PUBLIC_GATEWAY_URL"
|
||||
|
||||
# Commit the Markdown file if changed
|
||||
if ! git diff --quiet "$MARKDOWN_FILE" 2>/dev/null || ! git ls-files "$MARKDOWN_FILE" --error-unmatch >/dev/null 2>&1; then
|
||||
git add "$MARKDOWN_FILE"
|
||||
git commit -m "Update Radicle metadata at $TIMESTAMP — $PUBLIC_GATEWAY_URL" || warn "No changes to commit for $MARKDOWN_FILE"
|
||||
if git push rad "$CURRENT_BRANCH"; then
|
||||
echo "$CURRENT_COMMIT" > "$PUSH_STATE_FILE"
|
||||
info "✓ Pushed metadata update to Radicle"
|
||||
else
|
||||
warn "Metadata push failed — check 'rad sync status'"
|
||||
fi
|
||||
else
|
||||
info "No changes to $MARKDOWN_FILE; skipping commit."
|
||||
fi
|
185
gitfield-sync
Executable file
185
gitfield-sync
Executable file
|
@ -0,0 +1,185 @@
|
|||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
IFS=$'\n\t'
|
||||
|
||||
# ╭─────────────────────────────────────╮
|
||||
# │ CONFIGURATION │
|
||||
# ╰─────────────────────────────────────╯
|
||||
REPO_NAME=$(basename "$(pwd)")
|
||||
REPO_PATH=$(git rev-parse --show-toplevel)
|
||||
GITFIELD_DIR="$REPO_PATH/.gitfield"
|
||||
LOG_FILE="$GITFIELD_DIR/pushed.log"
|
||||
GITFIELD_MD="$REPO_PATH/GITFIELD.md"
|
||||
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
|
||||
SCRIPT_VERSION="1.0"
|
||||
|
||||
# URLs for each platform (derived from existing scripts)
|
||||
GITHUB_URL="https://github.com/mrhavens/$REPO_NAME"
|
||||
GITLAB_URL="https://gitlab.com/mrhavens/$REPO_NAME"
|
||||
BITBUCKET_URL="https://bitbucket.org/thefoldwithin/$REPO_NAME"
|
||||
RADICLE_PROJECT_ID="z45QC21eWL1F43VSbnV9AZbCZrHQJ" # From gitfield-radicle output
|
||||
RADICLE_URL="https://app.radicle.xyz/nodes/ash.radicle.garden/rad:$RADICLE_PROJECT_ID"
|
||||
|
||||
# ╭─────────────────────────────────────╮
|
||||
# │ LOGGING UTILS │
|
||||
# ╰─────────────────────────────────────╮
|
||||
info() { echo -e "\e[1;34m[INFO]\e[0m $*"; }
|
||||
warn() { echo -e "\e[1;33m[WARN]\e[0m $*"; }
|
||||
error() { echo -e "\e[1;31m[ERROR]\e[0m $*" >&2; exit 1; }
|
||||
|
||||
# ╭─────────────────────────────────────╮
|
||||
# │ INITIAL SETUP │
|
||||
# ╰─────────────────────────────────────╮
|
||||
# Ensure .gitfield directory exists
|
||||
mkdir -p "$GITFIELD_DIR"
|
||||
|
||||
# Initialize log file if it doesn't exist
|
||||
if [ ! -f "$LOG_FILE" ]; then
|
||||
echo "# Push Log for $REPO_NAME" > "$LOG_FILE"
|
||||
echo "# Generated by gitfield-sync" >> "$LOG_FILE"
|
||||
echo "" >> "$LOG_FILE"
|
||||
fi
|
||||
|
||||
# ╭─────────────────────────────────────╮
|
||||
# │ GENERATE GITFIELD.MD │
|
||||
# ╰─────────────────────────────────────╮
|
||||
generate_gitfield_md() {
|
||||
info "Generating $GITFIELD_MD..."
|
||||
cat > "$GITFIELD_MD" <<EOF
|
||||
# 🌐 GitField Recursive Multi-Repository Strategy
|
||||
|
||||
## Overview
|
||||
|
||||
The \`$REPO_NAME\` project employs a multi-repository strategy across four distinct platforms: **GitHub**, **GitLab**, **Bitbucket**, and **Radicle**. This approach ensures **redundancy**, **resilience**, and **sovereignty** of the project's data and metadata, protecting against deplatforming risks and preserving the integrity of the work. The strategy is a deliberate response to past deplatforming attempts by individuals such as **Mr. Joel Johnson** ([Mirror post](https://mirror.xyz/neutralizingnarcissism.eth/x40_zDWWrYOJ7nh8Y0fk06_3kNEP0KteSSRjPmXkiGg?utm_medium=social&utm_source=heylink.me)) and **Dr. Peter Gaied** ([Paragraph post](https://paragraph.com/@neutralizingnarcissism/%F0%9F%9C%81-the-narcissistic-messiah)), who have sought to undermine or suppress the work of **Mark Randall Havens** ([Substack post](https://theempathictechnologist.substack.com/p/mark-randall-havens-the-architect)). By distributing the repository across multiple platforms, we ensure its persistence and accessibility.
|
||||
|
||||
---
|
||||
|
||||
## 📍 Repository Platforms
|
||||
|
||||
The following platforms host the \`$REPO_NAME\` repository, each chosen for its unique strengths and contributions to the project's goals.
|
||||
|
||||
### 1. Radicle
|
||||
- **URL**: [$RADICLE_URL]($RADICLE_URL)
|
||||
- **Purpose**: Radicle is a decentralized, peer-to-peer git platform that ensures sovereignty and censorship resistance. It hosts the repository in a distributed network, independent of centralized servers.
|
||||
- **Value**: Protects against deplatforming by eliminating reliance on centralized infrastructure, ensuring the project remains accessible in a decentralized ecosystem.
|
||||
|
||||
### 2. GitLab
|
||||
- **URL**: [$GITLAB_URL]($GITLAB_URL)
|
||||
- **Purpose**: GitLab offers a comprehensive DevOps platform with advanced CI/CD capabilities, private repository options, and robust access controls. It serves as a reliable backup and a platform for advanced automation workflows.
|
||||
- **Value**: Enhances project resilience with its integrated CI/CD pipelines and independent infrastructure, reducing reliance on a single provider.
|
||||
|
||||
### 3. Bitbucket
|
||||
- **URL**: [$BITBUCKET_URL]($BITBUCKET_URL)
|
||||
- **Purpose**: Bitbucket provides a secure environment for repository hosting with strong integration into Atlassian’s ecosystem (e.g., Jira, Trello). It serves as an additional layer of redundancy and a professional-grade hosting option.
|
||||
- **Value**: Offers enterprise-grade security and integration capabilities, ensuring the project remains accessible even if other platforms face disruptions.
|
||||
|
||||
### 4. GitHub
|
||||
- **URL**: [$GITHUB_URL]($GITHUB_URL)
|
||||
- **Purpose**: GitHub serves as the primary platform for visibility, collaboration, and community engagement. Its widespread adoption and robust tooling make it ideal for public-facing development, issue tracking, and integration with CI/CD pipelines.
|
||||
- **Value**: Provides a centralized hub for open-source contributions, pull requests, and project management, ensuring broad accessibility and developer familiarity.
|
||||
|
||||
---
|
||||
|
||||
## 🛡️ Rationale for Redundancy
|
||||
|
||||
The decision to maintain multiple repositories stems from the need to safeguard the project against **deplatforming attempts** and ensure its **long-term availability**. Past incidents involving **Mr. Joel Johnson** and **Dr. Peter Gaied** have highlighted the vulnerability of relying on a single platform. By distributing the repository across GitHub, GitLab, Bitbucket, and Radicle, we achieve:
|
||||
|
||||
- **Resilience**: If one platform removes or restricts access, the project remains accessible on others.
|
||||
- **Sovereignty**: Radicle’s decentralized nature ensures the project cannot be fully censored or controlled by any single entity.
|
||||
- **Diversity**: Each platform’s unique features (e.g., GitHub’s community, GitLab’s CI/CD, Bitbucket’s integrations, Radicle’s decentralization) enhance the project’s functionality and reach.
|
||||
- **Transparency**: Metadata snapshots in the \`.gitfield\` directory provide a verifiable record of the project’s state across all platforms.
|
||||
|
||||
This multi-repository approach reflects a commitment to preserving the integrity and accessibility of \`$REPO_NAME\`, ensuring it remains available to contributors and users regardless of external pressures.
|
||||
|
||||
---
|
||||
|
||||
## 📜 Metadata and Logs
|
||||
|
||||
- **Metadata Files**: Each platform generates a metadata snapshot in the \`.gitfield\` directory (e.g., \`github.sigil.md\`, \`gitlab.sigil.md\`, etc.), capturing commit details, environment information, and hardware fingerprints.
|
||||
- **Push Log**: The \`.gitfield/pushed.log\` file records the date, time, and URL of every push operation across all platforms, providing a transparent audit trail.
|
||||
- **Recursive Sync**: The repository is synchronized across all platforms in a recursive loop (three cycles) to ensure interconnected metadata captures the latest state of the project.
|
||||
- **Push Order**: The repository is synchronized in the following order: **Radicle → GitLab → Bitbucket → GitHub**. This prioritizes Radicle’s decentralized, censorship-resistant network as the primary anchor, followed by GitLab’s robust DevOps features, Bitbucket’s enterprise redundancy, and GitHub’s broad visibility, ensuring a resilient and accessible metadata chain.
|
||||
|
||||
---
|
||||
|
||||
_Auto-generated by \`gitfield-sync\` at $TIMESTAMP (v$SCRIPT_VERSION)._
|
||||
EOF
|
||||
|
||||
# Add and commit GITFIELD.md
|
||||
git add "$GITFIELD_MD"
|
||||
git commit -m "Generated GITFIELD.md at $TIMESTAMP" || warn "No changes to commit for $GITFIELD_MD"
|
||||
info "Generated and committed $GITFIELD_MD"
|
||||
}
|
||||
|
||||
# ╭─────────────────────────────────────╮
|
||||
# │ LOG URL FUNCTION │
|
||||
# ╰─────────────────────────────────────╮
|
||||
log_url() {
|
||||
local platform=$1
|
||||
local url=$2
|
||||
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
||||
echo "[$timestamp] $platform: $url" >> "$LOG_FILE"
|
||||
info "Logged push to $LOG_FILE: [$timestamp] $platform: $url"
|
||||
}
|
||||
|
||||
# ╭─────────────────────────────────────╮
|
||||
# │ EXECUTE PUSH SCRIPT │
|
||||
# ╰─────────────────────────────────────╮
|
||||
execute_push() {
|
||||
local script=$1
|
||||
local platform=$2
|
||||
local url=$3
|
||||
info "Running $script for $platform..."
|
||||
if [ -x "$script" ]; then
|
||||
./"$script" || warn "Execution of $script failed, continuing..."
|
||||
# Log the URL after successful push
|
||||
log_url "$platform" "$url"
|
||||
# Add and commit any new files generated by the script
|
||||
git add . || warn "Nothing to add after $script"
|
||||
git commit -m "Post-$platform sync at $TIMESTAMP" || warn "No changes to commit after $script"
|
||||
else
|
||||
error "Script $script is not executable or does not exist"
|
||||
fi
|
||||
}
|
||||
|
||||
# ╭─────────────────────────────────────╮
|
||||
# │ RECURSIVE PUSH LOOP │
|
||||
# ╰─────────────────────────────────────╮
|
||||
run_push_cycle() {
|
||||
local cycle_number=$1
|
||||
info "Starting push cycle $cycle_number..."
|
||||
|
||||
# Push to each platform in order
|
||||
execute_push "gitfield-radicle" "Radicle" "$RADICLE_URL"
|
||||
execute_push "gitfield-gitlab" "GitLab" "$GITLAB_URL"
|
||||
execute_push "gitfield-bitbucket" "Bitbucket" "$BITBUCKET_URL"
|
||||
execute_push "gitfield-github" "GitHub" "$GITHUB_URL"
|
||||
}
|
||||
|
||||
# ╭─────────────────────────────────────╮
|
||||
# │ MAIN EXECUTION │
|
||||
# ╰─────────────────────────────────────╮
|
||||
info "Starting gitfield-sync for $REPO_NAME..."
|
||||
|
||||
# Ensure the repository is initialized
|
||||
if [ ! -d .git ]; then
|
||||
git init
|
||||
git add .
|
||||
git commit -m "Initial commit" || warn "Nothing to commit"
|
||||
fi
|
||||
|
||||
# Run the first push cycle
|
||||
run_push_cycle 1
|
||||
|
||||
# Generate GITFIELD.md after the first cycle
|
||||
generate_gitfield_md
|
||||
|
||||
# Run the second push cycle to include GITFIELD.md
|
||||
run_push_cycle 2
|
||||
|
||||
# Run the third push cycle for final metadata sync
|
||||
run_push_cycle 3
|
||||
|
||||
info "✅ gitfield-sync completed successfully."
|
||||
info "🔗 View logs: $LOG_FILE"
|
||||
info "🔗 View multi-repo manifest: $GITFIELD_MD"
|
1
index/all-titles.md
Normal file
1
index/all-titles.md
Normal file
|
@ -0,0 +1 @@
|
|||
# All Titles
|
1
index/master-cv.md
Normal file
1
index/master-cv.md
Normal file
|
@ -0,0 +1 @@
|
|||
# Master Cv
|
1
index/resume-snapshots/ai-ethics-resume.md
Normal file
1
index/resume-snapshots/ai-ethics-resume.md
Normal file
|
@ -0,0 +1 @@
|
|||
# Ai Ethics Resume
|
1
index/resume-snapshots/chaplain-resume.md
Normal file
1
index/resume-snapshots/chaplain-resume.md
Normal file
|
@ -0,0 +1 @@
|
|||
# Chaplain Resume
|
1
index/resume-snapshots/hospice-resume.md
Normal file
1
index/resume-snapshots/hospice-resume.md
Normal file
|
@ -0,0 +1 @@
|
|||
# Hospice Resume
|
1
output/chaplain-resume.pdf
Normal file
1
output/chaplain-resume.pdf
Normal file
|
@ -0,0 +1 @@
|
|||
# Chaplain Resume.Pdf
|
1
output/master-cv.pdf
Normal file
1
output/master-cv.pdf
Normal file
|
@ -0,0 +1 @@
|
|||
# Master Cv.Pdf
|
1
output/ministry-cv.pdf
Normal file
1
output/ministry-cv.pdf
Normal file
|
@ -0,0 +1 @@
|
|||
# Ministry Cv.Pdf
|
1
scripts/build.sh
Normal file
1
scripts/build.sh
Normal file
|
@ -0,0 +1 @@
|
|||
# Build.Sh
|
1
scripts/export.py
Normal file
1
scripts/export.py
Normal file
|
@ -0,0 +1 @@
|
|||
# Export.Py
|
1
templates/cv-template.md
Normal file
1
templates/cv-template.md
Normal file
|
@ -0,0 +1 @@
|
|||
# Cv Template
|
1
templates/letter-of-intent-template.md
Normal file
1
templates/letter-of-intent-template.md
Normal file
|
@ -0,0 +1 @@
|
|||
# Letter Of Intent Template
|
1
templates/resume-template.md
Normal file
1
templates/resume-template.md
Normal file
|
@ -0,0 +1 @@
|
|||
# Resume Template
|
Loading…
Add table
Add a link
Reference in a new issue