1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106 | #!/usr/bin/env bash
# assemble.sh — assembles and publishes a public source ecosystem at
# https://<HOST>: every repo clonable over plain HTTPS, no git server.
#
# ./assemble.sh rebuild + publish every repo
# ./assemble.sh app1 app2 rebuild only those; the rest stay as last assembled
# NO_PUBLISH=1 ./assemble.sh … assemble ROOT/ only, skip pin/publish
#
# TEMPLATE: set HOST and ROOT, fill in repo_for() and the default APPS list.
# Per app it runs the repo's own deploy/publish-repo.sh (which enforces the
# anonymity gate), then lays deploy/.site into ROOT/ as:
# ROOT/<app>.git/ dumb-HTTP-clonable bare mirror → https://<HOST>/<app>.git
# ROOT/<app>/ human page (index.html) → https://<HOST>/<app>/
# Finally: pin ROOT on IPFS, re-point the HOST IPNS name at the new CID, and
# unpin the previous root (IPFS dedupes unchanged subtrees, so an incremental
# publish costs roughly only the changed repo).
#
# One-time host setup (creates IPNS name + DNS records + TLS cert):
# ird ipfs ipns create <HOST> --serve
#
# Needs: ird CLI (logged in), jq, rsync. macOS bash 3.2 compatible.
set -euo pipefail
cd "$(dirname "$0")"
HOST=CHANGE-ME.example.ro
ROOT=site-root
repo_for() {
case "$1" in
app1) echo "$HOME/path/to/repo1" ;;
app2) echo "$HOME/path/to/repo2" ;;
*) echo "unknown app: $1 (known: app1 app2)" >&2; exit 1 ;;
esac
}
APPS=("$@")
[ ${#APPS[@]} -eq 0 ] && APPS=(app1 app2)
mkdir -p "$ROOT"
for app in "${APPS[@]}"; do
src=$(repo_for "$app")
echo "== $app ($src)"
"$src/deploy/publish-repo.sh"
rsync -a --delete "$src/deploy/.site/$app.git/" "$ROOT/$app.git/"
rsync -a --delete --exclude "$app.git" "$src/deploy/.site/" "$ROOT/$app/"
done
cp index.html "$ROOT/index.html"
# ---- releases.json: machine-readable coordinates of every published mirror
# (head, latest tag and its sha), read by the landing pages to fill their
# copy-paste dependency snippets and by scripts/agents directly
releases_json() {
local gd app head tag tag_sha
for gd in $ROOT/*.git; do
[ -d "$gd" ] || continue
app=$(basename "$gd" .git)
head=$(git --git-dir="$gd" rev-parse HEAD)
tag=$(git --git-dir="$gd" describe --tags --abbrev=0 HEAD 2>/dev/null || true)
tag_sha=""
[ -n "$tag" ] && tag_sha=$(git --git-dir="$gd" rev-parse "$tag^{commit}")
jq -n --arg app "$app" --arg host "$HOST" --arg head "$head" \
--arg tag "$tag" --arg tag_sha "$tag_sha" '
{($app): {
git: ("https://" + $host + "/" + $app + ".git"),
page: ("https://" + $host + "/" + $app + "/"),
head: $head, head_short: $head[0:7],
tag: (if $tag == "" then null else $tag end),
version: (if $tag == "" then null else ($tag | ltrimstr("v")) end),
tag_sha: (if $tag_sha == "" then null else $tag_sha end),
tag_sha_short: (if $tag_sha == "" then null else $tag_sha[0:7] end)}}'
done | jq -s --arg now "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
'{generated_at: $now, apps: (add // {})}' > "$ROOT/releases.json"
}
releases_json
if [ "${NO_PUBLISH:-0}" = "1" ]; then
echo "assembled $ROOT ($(du -sh "$ROOT" | cut -f1)) — NO_PUBLISH=1, stopping before pin/publish"
exit 0
fi
PIN_NAME="site:$HOST"
PREV=$(ird ipfs pins --json | jq -r --arg n "$PIN_NAME" \
'[.pins[]? | select(.name==$n and .state=="pinned")][0].cid // empty')
# stdout carries a cost table + progress lines before the JSON — keep from '{'
CID=$(ird ipfs add "$ROOT" --json --yes | sed -n '/^{/,$p' | jq -r '.root_cid // .pin.cid')
[ -n "$CID" ] && [ "$CID" != "null" ] || { echo "ABORT: could not read CID from ird ipfs add output" >&2; exit 1; }
# `ird ipfs add` names the pin after the folder — re-pin the same CID under
# $PIN_NAME (instant, content already on the node) and drop the folder-named
# entry, so the pin list reads site:<host>
if [ "$CID" != "$PREV" ]; then
ird ipfs pin "$CID" --name "$PIN_NAME" --yes >/dev/null
fi
TMP_ID=$(ird ipfs pins --json | jq -r --arg c "$CID" --arg n "$ROOT" \
'[.pins[]? | select(.cid==$c and .name==$n)][0].id // empty')
[ -n "$TMP_ID" ] && ird ipfs pin rm "$TMP_ID" --yes >/dev/null
echo "pinned $PIN_NAME -> $CID"
ird ipfs ipns publish "$HOST" "$CID" --yes
if [ -n "$PREV" ] && [ "$PREV" != "$CID" ]; then
ird ipfs pin rm "$PREV" --yes && echo "unpinned previous root $PREV"
fi
echo "published: https://$HOST -> $CID"
|