chore(repo): Umzug nach Gitea — GitHub bleibt Klon, main von Hand gespiegelt (D95)
Zuhause ist künftig git.javagil.de/mi/werkbaum (origin); GitHub bleibt unter dem Remote `github` ein Klon, den scripts/push-github.sh mit `main` versorgt — nur vorwärts, nie erzwungen. Der Klon bleibt aus zwei gemessenen Gründen: Gitea sendet auf raw-Dateien kein Access-Control-Allow-Origin (nachgemessen an mi/werkdock), die ?sourceUrl=-Beispiellinks der READMEs müssen also auf raw.githubusercontent.com zeigen; und der Pages-Workflow lässt sich nicht mitnehmen. Footer, llms.txt und llms.md zeigen jetzt auf Gitea (Repo-Seite ohne Anmeldung lesbar, HTTP 200 geprüft); beide COMMIT_URL-Stellen (deploy-prod.sh und der Pages-Workflow) ziehen mit. deploy-prod.sh prüft origin und github getrennt und erinnert an das Spiegeln, statt selbst zu pushen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
736e9c1d88
commit
29a217f892
@@ -76,7 +76,7 @@ jobs:
|
|||||||
[ -z "$BASE" ] && BASE="$(git rev-list --max-parents=0 HEAD | tail -1)"
|
[ -z "$BASE" ] && BASE="$(git rev-list --max-parents=0 HEAD | tail -1)"
|
||||||
MICRO="$(git rev-list --count "${BASE}..HEAD")" # Commits seit dem Bump
|
MICRO="$(git rev-list --count "${BASE}..HEAD")" # Commits seit dem Bump
|
||||||
BUILD_VERSION="${MAJORMINOR}.${MICRO}"
|
BUILD_VERSION="${MAJORMINOR}.${MICRO}"
|
||||||
COMMIT_URL="https://github.com/mhoennig/werkbaum/commit/$(git rev-parse HEAD)"
|
COMMIT_URL="https://git.javagil.de/mi/werkbaum/commit/$(git rev-parse HEAD)"
|
||||||
echo "Footer-Version: ${BUILD_VERSION} -> ${COMMIT_URL}"
|
echo "Footer-Version: ${BUILD_VERSION} -> ${COMMIT_URL}"
|
||||||
mkdir -p site
|
mkdir -p site
|
||||||
sed -e 's#\.\./LICENSE#LICENSE#g' \
|
sed -e 's#\.\./LICENSE#LICENSE#g' \
|
||||||
|
|||||||
+5
-5
@@ -4,12 +4,12 @@ werkator:
|
|||||||
version:
|
version:
|
||||||
since: "1.0.1"
|
since: "1.0.1"
|
||||||
|
|
||||||
# Commit status target. Points at GitHub for now; the repository will move to
|
# Commit status target. The repository lives on Gitea since D95; GitHub stays a
|
||||||
# https://git.javagil.de (Gitea) later, GitHub stays a synchronised clone. Status
|
# clone that `scripts/push-github.sh` feeds by hand. Status checks are posted
|
||||||
# checks are posted only once the origin is a Gitea; until then this is a label.
|
# only once the instance holds a Gitea token; until then this is a label.
|
||||||
gitea:
|
gitea:
|
||||||
baseUrl: https://github.com
|
baseUrl: https://git.javagil.de
|
||||||
owner: mhoennig
|
owner: mi
|
||||||
repo: werkbaum
|
repo: werkbaum
|
||||||
statusContext: werkator
|
statusContext: werkator
|
||||||
|
|
||||||
|
|||||||
+20
-3
@@ -142,6 +142,22 @@ Das Backend einrichten: siehe [backend/README.md](backend/README.md) und
|
|||||||
> `?etherpad=`-Link zeigt heute einen Hinweis hierher, statt still nichts zu
|
> `?etherpad=`-Link zeigt heute einen Hinweis hierher, statt still nichts zu
|
||||||
> tun; siehe `docs/DECISIONS.md` D78.
|
> tun; siehe `docs/DECISIONS.md` D78.
|
||||||
|
|
||||||
|
### Wo der Code liegt
|
||||||
|
|
||||||
|
Das Repository liegt auf **<https://git.javagil.de/mi/werkbaum>** (Gitea) — das
|
||||||
|
ist `origin`, und dort gehören die Branches hin:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone mih09-git@git.javagil.de:mi/werkbaum.git # oder https://git.javagil.de/mi/werkbaum.git
|
||||||
|
```
|
||||||
|
|
||||||
|
**GitHub bleibt ein Klon.** `main` wird dorthin von Hand gespiegelt
|
||||||
|
(`scripts/push-github.sh`), denn zwei Dinge hängen daran: die
|
||||||
|
GitHub-Pages-Instanz (der 🚧 *latest build* ganz oben) und die Beispiel-Links
|
||||||
|
weiter oben, die ihre Pläne per `?sourceUrl=` von `raw.githubusercontent.com`
|
||||||
|
laden. Gitea liefert `raw`-Dateien **ohne** `Access-Control-Allow-Origin` aus —
|
||||||
|
dort blockte der Browser sie (`docs/DECISIONS.md` D23, D95).
|
||||||
|
|
||||||
### Lokal ausführen
|
### Lokal ausführen
|
||||||
|
|
||||||
Die Editor-Quelle liegt jetzt als ES-Module unter `frontend/src/`, gebündelt mit
|
Die Editor-Quelle liegt jetzt als ES-Module unter `frontend/src/`, gebündelt mit
|
||||||
@@ -228,7 +244,8 @@ anderen Domain läge das Web-Verzeichnis in `…/subs-ssl/<name>/`.)
|
|||||||
|
|
||||||
Der Editor wird per GitHub Actions als statische Seite auf **GitHub Pages**
|
Der Editor wird per GitHub Actions als statische Seite auf **GitHub Pages**
|
||||||
veröffentlicht (Workflow: `.github/workflows/pages.yml`). Ausgelöst bei jedem
|
veröffentlicht (Workflow: `.github/workflows/pages.yml`). Ausgelöst bei jedem
|
||||||
Push auf `main` sowie manuell (`workflow_dispatch`).
|
Push auf `main` **des Klons** — also nachdem `scripts/push-github.sh` gespiegelt
|
||||||
|
hat (D95) — sowie manuell (`workflow_dispatch`).
|
||||||
|
|
||||||
Der Workflow richtet Node ein, führt `npm ci`, `npm test` (Vitest) und
|
Der Workflow richtet Node ein, führt `npm ci`, `npm test` (Vitest) und
|
||||||
`npm run build` (Vite) aus und veröffentlicht die gebündelte
|
`npm run build` (Vite) aus und veröffentlicht die gebündelte
|
||||||
@@ -244,8 +261,8 @@ gepflegt), die **Micro-Stelle** aus der Zahl der Commits seit diesem letzten
|
|||||||
Bump — sie steigt also mit jedem Commit und beginnt nach einem Bump wieder bei
|
Bump — sie steigt also mit jedem Commit und beginnt nach einem Bump wieder bei
|
||||||
`0` (`Werkbaum 1.0.0`, `1.0.1`, … dann `VERSION` auf `1.1` bumpen → `1.1.0`). Es
|
`0` (`Werkbaum 1.0.0`, `1.0.1`, … dann `VERSION` auf `1.1` bumpen → `1.1.0`). Es
|
||||||
wird nichts ins Repo zurückgeschrieben. Im Footer verlinkt der Name **Werkbaum**
|
wird nichts ins Repo zurückgeschrieben. Im Footer verlinkt der Name **Werkbaum**
|
||||||
die Repo-Startseite, die **Versionsnummer** genau den zugehörigen Commit
|
die Repo-Startseite auf Gitea, die **Versionsnummer** genau den zugehörigen
|
||||||
(`…/commit/<sha>`). Lokal geöffnet zeigt der Editor den Platzhalter aus dem
|
Commit dort (`…/commit/<sha>`) — der Klon trägt dieselben SHAs. Lokal geöffnet zeigt der Editor den Platzhalter aus dem
|
||||||
Quelltext (`Werkbaum 1.0`).
|
Quelltext (`Werkbaum 1.0`).
|
||||||
|
|
||||||
**Einmalige Einrichtung:** In den Repo-Settings unter **Pages** als **Source**
|
**Einmalige Einrichtung:** In den Repo-Settings unter **Pages** als **Source**
|
||||||
|
|||||||
@@ -136,6 +136,22 @@ Setting up the backend: see [backend/README.md](backend/README.md) and
|
|||||||
> old `?etherpad=` link now shows a note pointing here rather than silently
|
> old `?etherpad=` link now shows a note pointing here rather than silently
|
||||||
> doing nothing; see `docs/DECISIONS.md` D78.
|
> doing nothing; see `docs/DECISIONS.md` D78.
|
||||||
|
|
||||||
|
### Where the code lives
|
||||||
|
|
||||||
|
The repository is at **<https://git.javagil.de/mi/werkbaum>** (Gitea) — that is
|
||||||
|
`origin`, and that is where branches belong:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone mih09-git@git.javagil.de:mi/werkbaum.git # or https://git.javagil.de/mi/werkbaum.git
|
||||||
|
```
|
||||||
|
|
||||||
|
**GitHub stays a clone.** `main` is mirrored there by hand
|
||||||
|
(`scripts/push-github.sh`), because two things hang off it: the GitHub Pages
|
||||||
|
instance (the 🚧 *latest build* linked at the top) and the example links above,
|
||||||
|
which load plan files from `raw.githubusercontent.com` via `?sourceUrl=`. Gitea
|
||||||
|
serves raw files **without** an `Access-Control-Allow-Origin` header, so the
|
||||||
|
browser would block them there (`docs/DECISIONS.md` D23, D95).
|
||||||
|
|
||||||
### Running it locally
|
### Running it locally
|
||||||
|
|
||||||
The editor source now lives as ES modules under `frontend/src/`, bundled by
|
The editor source now lives as ES modules under `frontend/src/`, bundled by
|
||||||
@@ -225,7 +241,8 @@ directory would be `…/subs-ssl/<name>/`.)
|
|||||||
|
|
||||||
The editor is published as a static page on **GitHub Pages** via GitHub
|
The editor is published as a static page on **GitHub Pages** via GitHub
|
||||||
Actions (workflow: `.github/workflows/pages.yml`). Triggered on every push to
|
Actions (workflow: `.github/workflows/pages.yml`). Triggered on every push to
|
||||||
`main` and manually (`workflow_dispatch`).
|
`main` **of the clone** — that is, after `scripts/push-github.sh` has mirrored it
|
||||||
|
(D95) — and manually (`workflow_dispatch`).
|
||||||
|
|
||||||
The workflow sets up Node, runs `npm ci`, `npm test` (Vitest) and `npm run build`
|
The workflow sets up Node, runs `npm ci`, `npm test` (Vitest) and `npm run build`
|
||||||
(Vite), then publishes the bundled `frontend/dist/index.html` as `index.html` at
|
(Vite), then publishes the bundled `frontend/dist/index.html` as `index.html` at
|
||||||
@@ -240,8 +257,8 @@ commit"), and the **micro** part is the number of commits since that last bump
|
|||||||
so it grows with every commit and resets to `0` right after a bump
|
so it grows with every commit and resets to `0` right after a bump
|
||||||
(`Werkbaum 1.0.0`, `1.0.1`, … then bump `VERSION` to `1.1` → `1.1.0`). Nothing is
|
(`Werkbaum 1.0.0`, `1.0.1`, … then bump `VERSION` to `1.1` → `1.1.0`). Nothing is
|
||||||
written back to the repo. In the footer the name **Werkbaum** links to the
|
written back to the repo. In the footer the name **Werkbaum** links to the
|
||||||
repository, while the **version number** links to that exact commit
|
repository on Gitea, while the **version number** links to that exact commit
|
||||||
(`…/commit/<sha>`). Opened locally, the editor shows the source placeholder
|
there (`…/commit/<sha>`) — the clone carries the same SHAs. Opened locally, the editor shows the source placeholder
|
||||||
(`Werkbaum 1.0`).
|
(`Werkbaum 1.0`).
|
||||||
|
|
||||||
**One-time setup:** In the repo settings under **Pages**, select **Source** =
|
**One-time setup:** In the repo settings under **Pages**, select **Source** =
|
||||||
|
|||||||
@@ -17,6 +17,11 @@ the git history of `docs/examples/werkbaum.werkbaum`. A day can therefore carry
|
|||||||
a link without having a note (someone forgot to write one) — but never the
|
a link without having a note (someone forgot to write one) — but never the
|
||||||
reverse.
|
reverse.
|
||||||
|
|
||||||
|
## 2026-09-03
|
||||||
|
|
||||||
|
- The project moved to its own Gitea at git.javagil.de — the footer's repository and version links point there now, and GitHub stays a clone carrying the very same commits
|
||||||
|
- Every push is built by Werkator, the project's own CI, alongside the GitHub Pages build: backend and frontend as two named builds
|
||||||
|
|
||||||
## 2026-09-02
|
## 2026-09-02
|
||||||
|
|
||||||
- Running the installed app and a browser tab side by side works now: text, names and earlier states live under their own storage key per document and deleting leaves a tombstone, so windows stop deleting each other's work
|
- Running the installed app and a browser tab side by side works now: text, names and earlier states live under their own storage key per document and deleting leaves a tombstone, so windows stop deleting each other's work
|
||||||
|
|||||||
@@ -9089,3 +9089,58 @@ die Browser-Fläche war verborgen, getippt wurde per `value` + `input`
|
|||||||
D91-Nachtrag 9), und der Live-Feed ruht im dauerhaft verborgenen
|
D91-Nachtrag 9), und der Live-Feed ruht im dauerhaft verborgenen
|
||||||
Automatisierungs-Tab (D76-Nachtrag 1) — dass B A's Zeile sieht, ist deshalb
|
Automatisierungs-Tab (D76-Nachtrag 1) — dass B A's Zeile sieht, ist deshalb
|
||||||
über die Antwort auf den eigenen PATCH gemessen, nicht über den Feed.
|
über die Antwort auf den eigenen PATCH gemessen, nicht über den Feed.
|
||||||
|
|
||||||
|
## D95 — Das Repo zieht nach Gitea; GitHub bleibt ein Klon, von Hand gespiegelt (2026-09-03)
|
||||||
|
Werkbaum lag auf GitHub. Seit Werkator (die eigene CI, https://werkator.javagil.de)
|
||||||
|
die Builds fährt und `werkdock` bereits auf `git.javagil.de` liegt, gehört auch
|
||||||
|
Werkbaum dorthin: **`origin` ist jetzt `mi/werkbaum` auf Gitea**, GitHub bleibt
|
||||||
|
als **Klon** unter dem Remote `github` stehen.
|
||||||
|
|
||||||
|
**Der Klon ist kein Andenken, sondern zwei gemessene Zwänge:**
|
||||||
|
|
||||||
|
- **CORS.** Die Beispiel-Links beider READMEs laden ihre Pläne per
|
||||||
|
`?sourceUrl=` (D23) — und das geht nur, wenn die Quelle
|
||||||
|
`Access-Control-Allow-Origin` sendet. Nachgemessen an
|
||||||
|
`https://git.javagil.de/mi/werkdock/raw/branch/main/README.md` (mit
|
||||||
|
`Origin:`-Header): HTTP 200, `Access-Control-Expose-Headers`, aber **kein
|
||||||
|
`Access-Control-Allow-Origin`**. Ein Beispiel-Link auf Gitea liefe also
|
||||||
|
genau in den Fehler, den D23 als häufigsten benennt. `raw.githubusercontent.com`
|
||||||
|
sendet ihn (D24) — die Beispiel-Links bleiben deshalb dort.
|
||||||
|
- **GitHub Pages.** Die „latest build“-Instanz (D16) ist ein
|
||||||
|
Actions-Workflow und lässt sich nicht mitnehmen. Sie bleibt, und sie baut,
|
||||||
|
sobald `main` auf dem Klon ankommt.
|
||||||
|
|
||||||
|
**Gespiegelt wird von Hand, und nur `main`** (`scripts/push-github.sh`).
|
||||||
|
Feature-Branches und Tags bleiben in Gitea; was auf GitHub steht, ist der
|
||||||
|
veröffentlichte Stand. Erwogen und verworfen: **ein `origin` mit zwei
|
||||||
|
Push-URLs** (spiegelt bei jedem Push, auch bei Zwischenständen, und ein
|
||||||
|
Fehler an einer der beiden Seiten bricht den Push) und der **Voll-Mirror**
|
||||||
|
(`--mirror` löscht auf GitHub Branches, die in Gitea verschwunden sind — bei
|
||||||
|
einem öffentlichen Klon die unhöflichste Variante).
|
||||||
|
|
||||||
|
**Der Deploy spiegelt nicht, er erinnert.** `scripts/deploy-prod.sh` prüft
|
||||||
|
jetzt zweierlei getrennt: ob HEAD auf **origin (Gitea)** liegt — daran hängt
|
||||||
|
der Footer-Versionslink — und ob er auf **github** liegt; fehlt das zweite,
|
||||||
|
nennt es den Skript-Namen. Ausdrücklich so entschieden (Multiple-Choice): Ein
|
||||||
|
Deploy, der nebenbei woanders hin pusht, tut mehr, als sein Name sagt.
|
||||||
|
|
||||||
|
**Nie erzwungen.** Liegt `github/main` nicht in der Historie von `main`,
|
||||||
|
bricht das Spiegel-Script ab und zeigt `git log main..github/main`. Ein
|
||||||
|
Force-Push auf einen Klon, den andere geklont haben, ist eine bewusste
|
||||||
|
Handlung und keine Zeile in einem Hilfsskript.
|
||||||
|
|
||||||
|
**Die Links im Produkt zeigen auf Gitea** — Footer-Repo-Link und
|
||||||
|
Footer-Versionslink (`…/commit/<sha>`, D16), `llms.txt` und `llms.md` (D43).
|
||||||
|
Voraussetzung geprüft: Die Gitea-Instanz liefert Repo-Seite und API **ohne
|
||||||
|
Anmeldung** (HTTP 200). Die SHAs sind auf beiden Seiten dieselben, der Link
|
||||||
|
bleibt also auch für jemanden auflösbar, der vom Klon kommt. Beide
|
||||||
|
`COMMIT_URL`-Stellen ziehen mit — `deploy-prod.sh` **und** der
|
||||||
|
Pages-Workflow; das ist dieselbe Doppelpflege, die D16 schon für die
|
||||||
|
`sed`-Regeln benannt hat.
|
||||||
|
|
||||||
|
**Werkator:** Die `gitea:`-Sektion der `.werkator.yml` nennt jetzt
|
||||||
|
`git.javagil.de` / `mi` / `werkbaum` statt der GitHub-Platzhalter, und der
|
||||||
|
beobachtete Klon `~/werkbaum` auf mih09 bekommt Gitea als `origin` — sonst
|
||||||
|
sähe der Watcher neue Commits erst nach dem Spiegeln. **Status-Checks werden
|
||||||
|
weiterhin nicht gepostet**, solange auf der Instanz kein Gitea-Token liegt;
|
||||||
|
die Sektion ist bis dahin eine Beschriftung.
|
||||||
|
|||||||
@@ -124,6 +124,8 @@
|
|||||||
- [^] #bld.backend.proxy: Apache passes /api/ on, in .htaccess (XS) %% measured: the P flag is allowed
|
- [^] #bld.backend.proxy: Apache passes /api/ on, in .htaccess (XS) %% measured: the P flag is allowed
|
||||||
- [^] #bld.backend.remote: One command for everything on the server (S) %% remote <target> <action>
|
- [^] #bld.backend.remote: One command for everything on the server (S) %% remote <target> <action>
|
||||||
- [^] #bld.backend.backup: Save the database, and prove it can be read back (XS)
|
- [^] #bld.backend.backup: Save the database, and prove it can be read back (XS)
|
||||||
|
- [x] #bld.werkator: Also built by Werkator, the project's own CI (S) %% .werkator.yml, backend + frontend
|
||||||
|
- [x] #bld.gitea: The repository lives on Gitea, GitHub stays a clone (S)
|
||||||
- [-] #bld.ghpages: Deploy through a gh-pages branch (S) %% GitHub Actions instead
|
- [-] #bld.ghpages: Deploy through a gh-pages branch (S) %% GitHub Actions instead
|
||||||
- [-] #bld.gfonts: Fonts from Google (XS) %% self-hosted, no third-party request
|
- [-] #bld.gfonts: Fonts from Google (XS) %% self-hosted, no third-party request
|
||||||
- [ ] #be: Backend (XL)
|
- [ ] #be: Backend (XL)
|
||||||
@@ -853,6 +855,17 @@
|
|||||||
taken while the service runs can be torn. Stop, fetch, start again — and read
|
taken while the service runs can be torn. Stop, fetch, start again — and read
|
||||||
the archive back before trusting it.
|
the archive back before trusting it.
|
||||||
|
|
||||||
|
#bld.werkator
|
||||||
|
Werkator, the project's own declarative CI, builds every push from a
|
||||||
|
committed .werkator.yml — backend and frontend as two named builds. It builds
|
||||||
|
and tests only; deploying stays with the scripts.
|
||||||
|
|
||||||
|
#bld.gitea
|
||||||
|
The repository moved to Gitea; GitHub stays a clone that carries the
|
||||||
|
published main. The clone is not sentiment: the Pages instance hangs off it,
|
||||||
|
and so do the example links, which need a raw endpoint that sends CORS
|
||||||
|
headers.
|
||||||
|
|
||||||
#bld.ghpages
|
#bld.ghpages
|
||||||
Rejected: the official Actions route needs no extra branch and no deploy
|
Rejected: the official Actions route needs no extra branch and no deploy
|
||||||
key.
|
key.
|
||||||
|
|||||||
+1
-1
@@ -297,7 +297,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<footer class="site-footer"><a href="https://github.com/mhoennig/werkbaum" target="_blank" rel="noopener">Werkbaum</a> <a class="ver" href="https://github.com/mhoennig/werkbaum/commit/main" target="_blank" rel="noopener">1.0</a> · <a href="llms.md" target="_blank" rel="noopener" title="Werkbaum-Notation für KI-Agenten · Werkbaum notation for AI agents (Markdown)">llms.md</a> – © 2026 <a href="https://michael.hoennig.de" target="_blank" rel="noopener">Michael Hönnig</a> · <span class="vibe" title="Fable 5 and Opus 4.8">Built with Claude Code</span> – <a href="../LICENSE" target="_blank" rel="noopener">License</a> · <a href="https://michael.hoennig.de/imprint.html" target="_blank" rel="noopener" data-i18n="imprint">Impressum</a> · <a id="privacyLink" href="https://michael.hoennig.de/datenschutzerklaerung.html" target="_blank" rel="noopener" data-i18n="privacy">Datenschutz</a></footer>
|
<footer class="site-footer"><a href="https://git.javagil.de/mi/werkbaum" target="_blank" rel="noopener">Werkbaum</a> <a class="ver" href="https://git.javagil.de/mi/werkbaum/commit/main" target="_blank" rel="noopener">1.0</a> · <a href="llms.md" target="_blank" rel="noopener" title="Werkbaum-Notation für KI-Agenten · Werkbaum notation for AI agents (Markdown)">llms.md</a> – © 2026 <a href="https://michael.hoennig.de" target="_blank" rel="noopener">Michael Hönnig</a> · <span class="vibe" title="Fable 5 and Opus 4.8">Built with Claude Code</span> – <a href="../LICENSE" target="_blank" rel="noopener">License</a> · <a href="https://michael.hoennig.de/imprint.html" target="_blank" rel="noopener" data-i18n="imprint">Impressum</a> · <a id="privacyLink" href="https://michael.hoennig.de/datenschutzerklaerung.html" target="_blank" rel="noopener" data-i18n="privacy">Datenschutz</a></footer>
|
||||||
|
|
||||||
<!-- Knoten-Fenster für Touch-Geräte (D52): Ohne Zeiger gibt es keinen Tooltip.
|
<!-- Knoten-Fenster für Touch-Geräte (D52): Ohne Zeiger gibt es keinen Tooltip.
|
||||||
Es liegt auf <body> und ist `position:fixed` — in `#out` hinein würde es
|
Es liegt auf <body> und ist `position:fixed` — in `#out` hinein würde es
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
Werkbaum is a plain-text notation for work-breakdown structures (WBS) with
|
Werkbaum is a plain-text notation for work-breakdown structures (WBS) with
|
||||||
and/or decomposition. This guide teaches you to **read and write** it. The
|
and/or decomposition. This guide teaches you to **read and write** it. The
|
||||||
normative specification (German) is
|
normative specification (German) is
|
||||||
https://github.com/mhoennig/werkbaum/blob/main/docs/SPEC.md — if this guide
|
https://git.javagil.de/mi/werkbaum/src/branch/main/docs/SPEC.md — if this guide
|
||||||
and the SPEC disagree, the SPEC wins.
|
and the SPEC disagree, the SPEC wins.
|
||||||
|
|
||||||
Files are UTF-8 with LF line endings; the extension `.werkbaum` is a
|
Files are UTF-8 with LF line endings; the extension `.werkbaum` is a
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ is needed to store, share or version a plan.
|
|||||||
gates, status codes and progress ranks, sizes, node ids, dependencies,
|
gates, status codes and progress ranks, sizes, node ids, dependencies,
|
||||||
folding marks, descriptions, plus a complete example. Self-contained; start
|
folding marks, descriptions, plus a complete example. Self-contained; start
|
||||||
here.
|
here.
|
||||||
- [Specification](https://github.com/mhoennig/werkbaum/blob/main/docs/SPEC.md):
|
- [Specification](https://git.javagil.de/mi/werkbaum/src/branch/main/docs/SPEC.md):
|
||||||
The normative language definition (German). Where it and the guide disagree,
|
The normative language definition (German). Where it and the guide disagree,
|
||||||
it wins.
|
it wins.
|
||||||
- [Editor](https://werkbaum.javagil.de/): Renders a plan as a diagram.
|
- [Editor](https://werkbaum.javagil.de/): Renders a plan as a diagram.
|
||||||
@@ -26,8 +26,8 @@ is needed to store, share or version a plan.
|
|||||||
|
|
||||||
## Optional
|
## Optional
|
||||||
|
|
||||||
- [Design decisions](https://github.com/mhoennig/werkbaum/blob/main/docs/DECISIONS.md):
|
- [Design decisions](https://git.javagil.de/mi/werkbaum/src/branch/main/docs/DECISIONS.md):
|
||||||
Why the notation looks the way it does, at length (German). Background only,
|
Why the notation looks the way it does, at length (German). Background only,
|
||||||
not needed to read or write plans.
|
not needed to read or write plans.
|
||||||
- [Repository](https://github.com/mhoennig/werkbaum): Source and example plans
|
- [Repository](https://git.javagil.de/mi/werkbaum): Source and example plans
|
||||||
under `docs/examples/*.werkbaum`.
|
under `docs/examples/*.werkbaum`.
|
||||||
|
|||||||
+15
-6
@@ -117,13 +117,22 @@ if git -C "$ROOT" rev-parse HEAD >/dev/null 2>&1; then
|
|||||||
[ -z "$BASE" ] && BASE="$(git -C "$ROOT" rev-list --max-parents=0 HEAD | tail -1)"
|
[ -z "$BASE" ] && BASE="$(git -C "$ROOT" rev-list --max-parents=0 HEAD | tail -1)"
|
||||||
MICRO="$(git -C "$ROOT" rev-list --count "${BASE}..HEAD")"
|
MICRO="$(git -C "$ROOT" rev-list --count "${BASE}..HEAD")"
|
||||||
BUILD_VERSION="${MAJORMINOR}.${MICRO}"
|
BUILD_VERSION="${MAJORMINOR}.${MICRO}"
|
||||||
COMMIT_URL="https://github.com/mhoennig/werkbaum/commit/$(git -C "$ROOT" rev-parse HEAD)"
|
COMMIT_URL="https://git.javagil.de/mi/werkbaum/commit/$(git -C "$ROOT" rev-parse HEAD)"
|
||||||
echo "==> Footer-Version ${BUILD_VERSION} -> ${COMMIT_URL}"
|
echo "==> Footer-Version ${BUILD_VERSION} -> ${COMMIT_URL}"
|
||||||
# Der Link zeigt ins Leere, solange der Commit nicht auf GitHub liegt — nach
|
# Der Link zeigt auf Gitea (origin, D95) und läuft ins Leere, solange der
|
||||||
# einer Beförderung (Schritt 0) ist das der Normalfall.
|
# Commit dort nicht liegt — nach einer Beförderung (Schritt 0) ist das der
|
||||||
if [ -z "$(git -C "$ROOT" branch -r --contains HEAD 2>/dev/null)" ]; then
|
# Normalfall.
|
||||||
echo " ! HEAD liegt noch nicht auf origin — der Footer-Versionslink läuft" >&2
|
if ! git -C "$ROOT" branch -r --contains HEAD 2>/dev/null | grep -q "^ *origin/"; then
|
||||||
echo " ins Leere, bis 'git push' nachgeholt ist." >&2
|
echo " ! HEAD liegt noch nicht auf origin (Gitea) — der Footer-Versionslink" >&2
|
||||||
|
echo " läuft ins Leere, bis 'git push' nachgeholt ist." >&2
|
||||||
|
fi
|
||||||
|
# GitHub ist seit D95 nur noch ein Klon und wird VON HAND gespiegelt. Der
|
||||||
|
# Deploy spiegelt nicht selbst — er erinnert nur, denn die Pages-Instanz und
|
||||||
|
# die ?sourceUrl=-Beispiellinks (raw.githubusercontent.com) hängen daran.
|
||||||
|
if git -C "$ROOT" remote get-url github >/dev/null 2>&1 &&
|
||||||
|
! git -C "$ROOT" branch -r --contains HEAD 2>/dev/null | grep -q "^ *github/"; then
|
||||||
|
echo " ! HEAD liegt noch nicht auf github — der Klon hinkt hinterher;" >&2
|
||||||
|
echo " 'scripts/push-github.sh' holt es nach." >&2
|
||||||
fi
|
fi
|
||||||
SED_ARGS+=(-e "s#\(<a class=\"ver\" href=\"\)[^\"]*#\1${COMMIT_URL}#")
|
SED_ARGS+=(-e "s#\(<a class=\"ver\" href=\"\)[^\"]*#\1${COMMIT_URL}#")
|
||||||
SED_ARGS+=(-e "s#\(<a class=\"ver\"[^>]*>\)[0-9.]\+</a>#\1${BUILD_VERSION}</a>#")
|
SED_ARGS+=(-e "s#\(<a class=\"ver\"[^>]*>\)[0-9.]\+</a>#\1${BUILD_VERSION}</a>#")
|
||||||
|
|||||||
Executable
+97
@@ -0,0 +1,97 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# Werkbaum — main nach GitHub spiegeln.
|
||||||
|
#
|
||||||
|
# Zuhause des Repos ist seit D95 Gitea (`origin`, https://git.javagil.de/mi/werkbaum);
|
||||||
|
# GitHub bleibt ein Klon unter `github`. Dieser Lauf schiebt genau EINEN Branch
|
||||||
|
# dorthin: `main`. Feature-Branches und Tags bleiben in Gitea — was auf GitHub
|
||||||
|
# steht, ist der veröffentlichte Stand.
|
||||||
|
#
|
||||||
|
# Der Klon ist kein Selbstzweck. An ihm hängen zwei Dinge, die nicht umziehen
|
||||||
|
# können:
|
||||||
|
# * der GitHub-Pages-Workflow (`.github/workflows/pages.yml`), also die
|
||||||
|
# „latest build"-Instanz mhoennig.github.io/werkbaum;
|
||||||
|
# * die Beispiel-Links der READMEs, die per `?sourceUrl=` von
|
||||||
|
# raw.githubusercontent.com laden — Gitea sendet auf `raw`-Dateien KEIN
|
||||||
|
# `Access-Control-Allow-Origin`, der Browser blockte sie also (D23, D95).
|
||||||
|
#
|
||||||
|
# Verwendung:
|
||||||
|
# scripts/push-github.sh [-n] [-y]
|
||||||
|
#
|
||||||
|
# -n, --dry-run nur zeigen, was gepusht würde
|
||||||
|
# -y, --yes ohne Rückfrage pushen
|
||||||
|
#
|
||||||
|
# Aufgerufen wird von Hand. `scripts/deploy-prod.sh` spiegelt NICHT selbst — es
|
||||||
|
# erinnert nur, wenn der deployte Commit noch nicht auf GitHub liegt (D95).
|
||||||
|
#
|
||||||
|
# Es wird nie erzwungen: Liegt github/main nicht in der Historie von main,
|
||||||
|
# bricht der Lauf ab und sagt, was er gefunden hat. Ein Force-Push auf einen
|
||||||
|
# Klon, den andere geklont haben, ist eine bewusste Handlung und keine Zeile in
|
||||||
|
# einem Hilfsskript.
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
DRY=0
|
||||||
|
YES=0
|
||||||
|
for arg in "$@"; do
|
||||||
|
case "$arg" in
|
||||||
|
-n|--dry-run) DRY=1 ;;
|
||||||
|
-y|--yes) YES=1 ;;
|
||||||
|
-h|--help)
|
||||||
|
awk 'NR>2 { if ($0 ~ /^#/) { sub(/^# ?/, ""); print } else exit }' "$0"
|
||||||
|
exit 0 ;;
|
||||||
|
*) echo "Unbekannte Option: $arg" >&2; exit 2 ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
cd "$ROOT"
|
||||||
|
|
||||||
|
REMOTE="${GITHUB_REMOTE:-github}"
|
||||||
|
|
||||||
|
git remote get-url "$REMOTE" >/dev/null 2>&1 || {
|
||||||
|
echo "Kein Remote '$REMOTE'. Einmalig anlegen:" >&2
|
||||||
|
echo " git remote add $REMOTE git@github.com:mhoennig/werkbaum.git" >&2
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "==> Hole $REMOTE"
|
||||||
|
git fetch --quiet "$REMOTE" || {
|
||||||
|
echo "Konnte $REMOTE nicht holen." >&2; exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
LOCAL="$(git rev-parse main)"
|
||||||
|
REMOTE_SHA="$(git rev-parse "$REMOTE/main" 2>/dev/null || echo "")"
|
||||||
|
|
||||||
|
if [ "$LOCAL" = "$REMOTE_SHA" ]; then
|
||||||
|
echo "==> $REMOTE/main ist bereits auf $(git rev-parse --short main) — nichts zu tun."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Nur vorwärts. Ist der Fernstand kein Vorfahr, hat dort jemand etwas liegen,
|
||||||
|
# das ein Push wegwürfe — dann lieber abbrechen als überschreiben.
|
||||||
|
if [ -n "$REMOTE_SHA" ] && ! git merge-base --is-ancestor "$REMOTE_SHA" "$LOCAL"; then
|
||||||
|
echo "ABBRUCH: $REMOTE/main ($(git rev-parse --short "$REMOTE/main")) liegt nicht in der" >&2
|
||||||
|
echo "Historie von main ($(git rev-parse --short main)) — ein Push würde dort Commits" >&2
|
||||||
|
echo "verlieren. Erst ansehen:" >&2
|
||||||
|
echo " git log --oneline main..$REMOTE/main" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$REMOTE_SHA" ]; then RANGE="$REMOTE_SHA..main"; else RANGE="main"; fi
|
||||||
|
echo "==> $(git rev-list --count "$RANGE") Commit(s) nach $REMOTE/main zu spiegeln:"
|
||||||
|
git --no-pager log --oneline "$RANGE" | head -20
|
||||||
|
|
||||||
|
if [ "$DRY" = "1" ]; then
|
||||||
|
echo "==> --dry-run: nichts gepusht."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$YES" != "1" ]; then
|
||||||
|
read -r -p "main nach $REMOTE pushen? [j/N] " a
|
||||||
|
case "$a" in j|J|y|Y) ;; *) echo "Abgebrochen."; exit 0 ;; esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
git push "$REMOTE" main:main
|
||||||
|
echo "==> main auf $REMOTE ist jetzt $(git rev-parse --short main)."
|
||||||
|
echo " Der Pages-Workflow baut daraufhin von selbst."
|
||||||
Reference in New Issue
Block a user