mirror of
https://github.com/brunopostle/ifcurl.git
synced 2026-07-12 02:08:13 +00:00
forgejo: systemd unit, ifcmerge driver docs; fix stale proxy mention
- forgejo/server-config/ifcurl-preview.service: systemd unit for the preview service with dedicated user, EnvironmentFile for cache config, and --allowed-hosts in ExecStart - forgejo/server-config/gitconfig-ifcmerge: registers two [merge] driver variants (ifcmerge and ifcmerge_ours) for the asymmetric .ifc merge case - forgejo/README.md: systemd deployment section (manual + service), ifcmerge section covering Perl script install, driver registration, per-repo gitattributes, and merge-direction constraint (merge-commit preserves main's IDs) - README.md: remove stale "IFC file proxy" description; update quick-summary to show systemd install path Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
335349db1a
commit
e824f9fd0e
5 changed files with 151 additions and 7 deletions
|
|
@ -30,7 +30,7 @@
|
||||||
{"id":"ifcurl-lcr","title":"Phase 4: Bonsai 'Copy view URL' button","description":"Add a button to Bonsai that generates an ifc:// URL from the current state: git remote/ref/file path, active selection as IfcOpenShell selector, current camera as camera+fov or scale params in IFC world coordinates, active clipping planes as clip params, current visibility mode. Default to commit hash ref; secondary option for @heads/ ref.","status":"deferred","priority":3,"issue_type":"feature","owner":"bruno@postle.net","created_at":"2026-04-23T05:48:55Z","created_by":"Bruno Postle","updated_at":"2026-04-23T06:15:10Z","defer_until":"2026-12-01T00:00:00Z","dependencies":[{"issue_id":"ifcurl-lcr","depends_on_id":"ifcurl-0oj","type":"blocks","created_at":"2026-04-23T06:49:01Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0}
|
{"id":"ifcurl-lcr","title":"Phase 4: Bonsai 'Copy view URL' button","description":"Add a button to Bonsai that generates an ifc:// URL from the current state: git remote/ref/file path, active selection as IfcOpenShell selector, current camera as camera+fov or scale params in IFC world coordinates, active clipping planes as clip params, current visibility mode. Default to commit hash ref; secondary option for @heads/ ref.","status":"deferred","priority":3,"issue_type":"feature","owner":"bruno@postle.net","created_at":"2026-04-23T05:48:55Z","created_by":"Bruno Postle","updated_at":"2026-04-23T06:15:10Z","defer_until":"2026-12-01T00:00:00Z","dependencies":[{"issue_id":"ifcurl-lcr","depends_on_id":"ifcurl-0oj","type":"blocks","created_at":"2026-04-23T06:49:01Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0}
|
||||||
{"id":"ifcurl-0oj","title":"Phase 4: Bonsai ifc:// OS protocol handler","description":"Register ifc:// as an OS protocol handler in Bonsai on installation (Windows, macOS, Linux). On receiving a URL, resolve the git source, load the model, and apply the view state from the URL parameters (camera, selector, clipping planes, visibility mode). This is the foundation for all other Phase 4 work.","status":"deferred","priority":3,"issue_type":"feature","owner":"bruno@postle.net","created_at":"2026-04-23T05:48:45Z","created_by":"Bruno Postle","updated_at":"2026-04-23T06:15:09Z","defer_until":"2026-12-01T00:00:00Z","dependency_count":0,"dependent_count":3,"comment_count":0}
|
{"id":"ifcurl-0oj","title":"Phase 4: Bonsai ifc:// OS protocol handler","description":"Register ifc:// as an OS protocol handler in Bonsai on installation (Windows, macOS, Linux). On receiving a URL, resolve the git source, load the model, and apply the view state from the URL parameters (camera, selector, clipping planes, visibility mode). This is the foundation for all other Phase 4 work.","status":"deferred","priority":3,"issue_type":"feature","owner":"bruno@postle.net","created_at":"2026-04-23T05:48:45Z","created_by":"Bruno Postle","updated_at":"2026-04-23T06:15:09Z","defer_until":"2026-12-01T00:00:00Z","dependency_count":0,"dependent_count":3,"comment_count":0}
|
||||||
{"id":"ifcurl-cyw","title":"Phase 3c: Verify Forgejo merge-ability check works with ifcmerge","description":"Investigate whether Forgejo's merge-ability check (the 'branches can be merged automatically' indicator) correctly reflects ifcmerge's ability to handle .ifc files. Determine if Forgejo runs a trial git merge or uses a heuristic. If needed, patch Forgejo to run a trial git merge --no-commit to get an accurate result.","status":"open","priority":3,"issue_type":"task","owner":"bruno@postle.net","created_at":"2026-04-23T05:48:22Z","created_by":"Bruno Postle","updated_at":"2026-04-23T05:48:22Z","dependencies":[{"issue_id":"ifcurl-cyw","depends_on_id":"ifcurl-c69","type":"blocks","created_at":"2026-04-23T06:48:29Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0}
|
{"id":"ifcurl-cyw","title":"Phase 3c: Verify Forgejo merge-ability check works with ifcmerge","description":"Investigate whether Forgejo's merge-ability check (the 'branches can be merged automatically' indicator) correctly reflects ifcmerge's ability to handle .ifc files. Determine if Forgejo runs a trial git merge or uses a heuristic. If needed, patch Forgejo to run a trial git merge --no-commit to get an accurate result.","status":"open","priority":3,"issue_type":"task","owner":"bruno@postle.net","created_at":"2026-04-23T05:48:22Z","created_by":"Bruno Postle","updated_at":"2026-04-23T05:48:22Z","dependencies":[{"issue_id":"ifcurl-cyw","depends_on_id":"ifcurl-c69","type":"blocks","created_at":"2026-04-23T06:48:29Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0}
|
||||||
{"id":"ifcurl-c69","title":"Phase 3c: Register ifcmerge as git merge driver on Forgejo server","description":"Configure ifcmerge as the git merge driver for .ifc files on the Forgejo server. Add to /etc/gitconfig or ~forgejo/.gitconfig: [merge \"ifcmerge\"] name = IFC merge driver / driver = ifcmerge %O %A %B %L. Add *.ifc merge=ifcmerge to server-side gitattributes. This allows Forgejo's 'merge automatically' path to invoke ifcmerge via git when merging .ifc files.","status":"open","priority":3,"issue_type":"task","owner":"bruno@postle.net","created_at":"2026-04-23T05:48:21Z","created_by":"Bruno Postle","updated_at":"2026-04-23T05:48:21Z","comments":[{"id":"019dbc54-bf0a-76e2-b64d-7d1681f0c730","issue_id":"ifcurl-c69","author":"Bruno Postle","text":"ifcmerge needs to be installed as a pair of merge tools because the merge process is asymmetrical and we need to be able to prefer one branch over another (because step-ids from one branch get rewritten in the merged file). In practice we prefer origin and/or main/master branches. there is code in the ifcopenshell bonsai ifcgit module for reference.","created_at":"2026-04-23T21:52:44Z"}],"dependency_count":0,"dependent_count":1,"comment_count":1}
|
{"id":"ifcurl-c69","title":"Phase 3c: Register ifcmerge as git merge driver on Forgejo server","description":"Configure ifcmerge as the git merge driver for .ifc files on the Forgejo server. Add to /etc/gitconfig or ~forgejo/.gitconfig: [merge \"ifcmerge\"] name = IFC merge driver / driver = ifcmerge %O %A %B %L. Add *.ifc merge=ifcmerge to server-side gitattributes. This allows Forgejo's 'merge automatically' path to invoke ifcmerge via git when merging .ifc files.","status":"closed","priority":3,"issue_type":"task","owner":"bruno@postle.net","created_at":"2026-04-23T05:48:21Z","created_by":"Bruno Postle","updated_at":"2026-04-24T08:15:20Z","closed_at":"2026-04-24T08:15:20Z","close_reason":"Documented ifcmerge driver registration (gitconfig-ifcmerge), gitattributes setup, merge direction constraint, and merge-commit strategy requirement","comments":[{"id":"019dbc54-bf0a-76e2-b64d-7d1681f0c730","issue_id":"ifcurl-c69","author":"Bruno Postle","text":"ifcmerge needs to be installed as a pair of merge tools because the merge process is asymmetrical and we need to be able to prefer one branch over another (because step-ids from one branch get rewritten in the merged file). In practice we prefer origin and/or main/master branches. there is code in the ifcopenshell bonsai ifcgit module for reference.","created_at":"2026-04-23T21:52:44Z"}],"dependency_count":0,"dependent_count":1,"comment_count":1}
|
||||||
{"id":"ifcurl-8ns","title":"Future: Contribute ifc:// URL parsing to IfcOpenShell","description":"Once the Python core URL parsing and resolution logic is stable, contribute it to IfcOpenShell as a shared utility. Not a prerequisite for any phase — pursue after Phase 1 has been stable in production use for a while.","status":"open","priority":4,"issue_type":"task","owner":"bruno@postle.net","created_at":"2026-04-23T05:49:33Z","created_by":"Bruno Postle","updated_at":"2026-04-23T05:49:33Z","dependency_count":0,"dependent_count":0,"comment_count":0}
|
{"id":"ifcurl-8ns","title":"Future: Contribute ifc:// URL parsing to IfcOpenShell","description":"Once the Python core URL parsing and resolution logic is stable, contribute it to IfcOpenShell as a shared utility. Not a prerequisite for any phase — pursue after Phase 1 has been stable in production use for a while.","status":"open","priority":4,"issue_type":"task","owner":"bruno@postle.net","created_at":"2026-04-23T05:49:33Z","created_by":"Bruno Postle","updated_at":"2026-04-23T05:49:33Z","dependency_count":0,"dependent_count":0,"comment_count":0}
|
||||||
{"id":"ifcurl-9yr","title":"Future: BCF export endpoint /bcf","description":"Add a /bcf endpoint to the preview service: POST /bcf with body {url: 'ifc://...'} returns a BCF zip file. Resolve the selector to a GUID set and construct a BCF viewpoint from the camera, clipping planes, and visibility state. Not planned before Phase 2 is complete.","status":"open","priority":4,"issue_type":"feature","owner":"bruno@postle.net","created_at":"2026-04-23T05:49:25Z","created_by":"Bruno Postle","updated_at":"2026-04-23T05:49:25Z","dependency_count":0,"dependent_count":0,"comment_count":0}
|
{"id":"ifcurl-9yr","title":"Future: BCF export endpoint /bcf","description":"Add a /bcf endpoint to the preview service: POST /bcf with body {url: 'ifc://...'} returns a BCF zip file. Resolve the selector to a GUID set and construct a BCF viewpoint from the camera, clipping planes, and visibility state. Not planned before Phase 2 is complete.","status":"open","priority":4,"issue_type":"feature","owner":"bruno@postle.net","created_at":"2026-04-23T05:49:25Z","created_by":"Bruno Postle","updated_at":"2026-04-23T05:49:25Z","dependency_count":0,"dependent_count":0,"comment_count":0}
|
||||||
{"id":"ifcurl-vam","title":"Phase 6: Bonsai offer ifc:// URL when saving linked model reference","description":"When saving an IFCDOCUMENTREFERENCE in Bonsai, offer the option to write the location as an ifc:// URL rather than a relative path. When a relative path would traverse above the repository root, prompt the user to convert it to an ifc:// URL. Requires Phase 4 federation (ifcurl-bqt).","status":"deferred","priority":4,"issue_type":"feature","owner":"bruno@postle.net","created_at":"2026-04-23T05:49:16Z","created_by":"Bruno Postle","updated_at":"2026-04-23T06:15:13Z","defer_until":"2026-12-01T00:00:00Z","dependencies":[{"issue_id":"ifcurl-vam","depends_on_id":"ifcurl-bqt","type":"blocks","created_at":"2026-04-23T06:49:23Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0}
|
{"id":"ifcurl-vam","title":"Phase 6: Bonsai offer ifc:// URL when saving linked model reference","description":"When saving an IFCDOCUMENTREFERENCE in Bonsai, offer the option to write the location as an ifc:// URL rather than a relative path. When a relative path would traverse above the repository root, prompt the user to convert it to an ifc:// URL. Requires Phase 4 federation (ifcurl-bqt).","status":"deferred","priority":4,"issue_type":"feature","owner":"bruno@postle.net","created_at":"2026-04-23T05:49:16Z","created_by":"Bruno Postle","updated_at":"2026-04-23T06:15:13Z","defer_until":"2026-12-01T00:00:00Z","dependencies":[{"issue_id":"ifcurl-vam","depends_on_id":"ifcurl-bqt","type":"blocks","created_at":"2026-04-23T06:49:23Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ Four interlocking components:
|
||||||
| Component | Language | What it does |
|
| Component | Language | What it does |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| **Python library + CLI** | Python | Parse ifc:// URLs, fetch IFC from git, render PNG |
|
| **Python library + CLI** | Python | Parse ifc:// URLs, fetch IFC from git, render PNG |
|
||||||
| **Preview service** | Python | HTTP server — PNGs on demand, IFC file proxy |
|
| **Preview service** | Python | HTTP server — PNGs on demand |
|
||||||
| **Forgejo integration** | Go + assets | Inline markdown previews, "View in 3D" button |
|
| **Forgejo integration** | Go + assets | Inline markdown previews, "View in 3D" button |
|
||||||
| **Browser viewer** | JavaScript | Interactive WebGL viewer, served as a Forgejo asset |
|
| **Browser viewer** | JavaScript | Interactive WebGL viewer, served as a Forgejo asset |
|
||||||
|
|
||||||
|
|
@ -183,8 +183,10 @@ sudo cp forgejo/custom/public/assets/viewer*.* /etc/forgejo/public/assets/
|
||||||
sudo cp forgejo/templates/custom/footer.tmpl /var/lib/forgejo/custom/templates/custom/
|
sudo cp forgejo/templates/custom/footer.tmpl /var/lib/forgejo/custom/templates/custom/
|
||||||
sudo systemctl restart forgejo
|
sudo systemctl restart forgejo
|
||||||
|
|
||||||
# Start preview service (restrict to this Forgejo host)
|
# Install and start preview service as a systemd unit
|
||||||
ifcurl serve --allowed-hosts git.example.com
|
sudo cp forgejo/server-config/ifcurl-preview.service /etc/systemd/system/
|
||||||
|
# edit ExecStart --allowed-hosts to match your Forgejo hostname, then:
|
||||||
|
sudo systemctl enable --now ifcurl-preview
|
||||||
```
|
```
|
||||||
|
|
||||||
Add to `/etc/forgejo/conf/app.ini`:
|
Add to `/etc/forgejo/conf/app.ini`:
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,9 @@ forgejo/
|
||||||
viewer-url.js ← viewer URL logic module
|
viewer-url.js ← viewer URL logic module
|
||||||
templates/custom/
|
templates/custom/
|
||||||
footer.tmpl ← "View in 3D" button injection
|
footer.tmpl ← "View in 3D" button injection
|
||||||
|
server-config/
|
||||||
|
ifcurl-preview.service ← systemd unit for the preview service
|
||||||
|
gitconfig-ifcmerge ← git merge driver config for .ifc files
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
@ -116,10 +119,40 @@ sudo systemctl restart forgejo
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Starting the preview service
|
## Running the preview service
|
||||||
|
|
||||||
Run the preview service co-located with Forgejo, passing `--allowed-hosts`
|
### As a systemd service (recommended)
|
||||||
set to your Forgejo hostname so the service will only fetch from that instance:
|
|
||||||
|
A systemd unit is provided at `server-config/ifcurl-preview.service`.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create a dedicated user
|
||||||
|
sudo useradd --system --no-create-home --shell /usr/sbin/nologin ifcurl
|
||||||
|
|
||||||
|
# Install the unit (edit AllowedHosts and port first)
|
||||||
|
sudo cp forgejo/server-config/ifcurl-preview.service /etc/systemd/system/
|
||||||
|
sudo systemctl daemon-reload
|
||||||
|
sudo systemctl enable --now ifcurl-preview
|
||||||
|
```
|
||||||
|
|
||||||
|
Edit the `ExecStart` line to set your Forgejo hostname:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
ExecStart=/usr/local/bin/ifcurl serve \
|
||||||
|
--host 127.0.0.1 \
|
||||||
|
--port 8000 \
|
||||||
|
--allowed-hosts git.example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
Cache limits and other environment variables can be set in
|
||||||
|
`/etc/ifcurl/env` (one `KEY=value` per line):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
IFCURL_CACHE_MAX_GB=10
|
||||||
|
IFCURL_T2_MAX=16
|
||||||
|
```
|
||||||
|
|
||||||
|
### Manually (for testing)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
ifcurl serve --allowed-hosts git.example.com
|
ifcurl serve --allowed-hosts git.example.com
|
||||||
|
|
@ -150,6 +183,72 @@ no preview image.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## IFC merge driver (ifcmerge)
|
||||||
|
|
||||||
|
Configuring `ifcmerge` as the git merge driver for `.ifc` files lets Forgejo
|
||||||
|
automatically merge IFC pull requests instead of marking them as conflicted.
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
`ifcmerge` is a single Perl script from
|
||||||
|
[github.com/brunopostle/ifcmerge](https://github.com/brunopostle/ifcmerge).
|
||||||
|
Download and install it on the Forgejo server:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -o /usr/local/bin/ifcmerge \
|
||||||
|
https://raw.githubusercontent.com/brunopostle/ifcmerge/main/ifcmerge
|
||||||
|
chmod +x /usr/local/bin/ifcmerge
|
||||||
|
```
|
||||||
|
|
||||||
|
Verify it is on `PATH` for the `forgejo` system user:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo -u forgejo which ifcmerge
|
||||||
|
```
|
||||||
|
|
||||||
|
### Register the merge drivers
|
||||||
|
|
||||||
|
Append `server-config/gitconfig-ifcmerge` to the server's global git config:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo git config --system --add include.path /path/to/forgejo/server-config/gitconfig-ifcmerge
|
||||||
|
```
|
||||||
|
|
||||||
|
Or copy the two `[merge "…"]` blocks directly into `/etc/gitconfig`.
|
||||||
|
|
||||||
|
### Set the per-repository gitattributes
|
||||||
|
|
||||||
|
Add a `.gitattributes` file to each IFC repository:
|
||||||
|
|
||||||
|
```
|
||||||
|
*.ifc merge=ifcmerge
|
||||||
|
```
|
||||||
|
|
||||||
|
Or set a server-wide default by adding to
|
||||||
|
`/usr/share/git-core/templates/info/attributes` (applied to all newly
|
||||||
|
initialised repos):
|
||||||
|
|
||||||
|
```
|
||||||
|
*.ifc merge=ifcmerge
|
||||||
|
```
|
||||||
|
|
||||||
|
### Merge direction
|
||||||
|
|
||||||
|
The merge driver is asymmetrical: `ifcmerge` rewrites STEP IDs from `%B`
|
||||||
|
(theirs) to match `%A` (ours), so `%A`'s ID space is preserved in the
|
||||||
|
merged file.
|
||||||
|
|
||||||
|
For Forgejo, use the **"Merge commit"** strategy (not rebase or squash).
|
||||||
|
With a merge commit, `%A` is always the base branch (e.g. `main`) and
|
||||||
|
`%B` is the pull-request branch — so `main`'s STEP IDs are preserved and
|
||||||
|
existing cross-references remain valid.
|
||||||
|
|
||||||
|
A second driver `ifcmerge_ours` is defined in the config file for cases
|
||||||
|
where the base branch arrives as `%B`; see the comments in
|
||||||
|
`server-config/gitconfig-ifcmerge` for details.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Upgrading Forgejo
|
## Upgrading Forgejo
|
||||||
|
|
||||||
After upgrading Forgejo upstream:
|
After upgrading Forgejo upstream:
|
||||||
|
|
|
||||||
19
forgejo/server-config/gitconfig-ifcmerge
Normal file
19
forgejo/server-config/gitconfig-ifcmerge
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
# Add to /etc/gitconfig (or ~forgejo/.gitconfig) on the Forgejo server.
|
||||||
|
#
|
||||||
|
# Two drivers are registered because the merge is asymmetrical — ifcmerge
|
||||||
|
# rewrites STEP IDs from %B to match %A's ID space. The base-branch must
|
||||||
|
# always be %A so its IDs are preserved.
|
||||||
|
#
|
||||||
|
# ifcmerge — use when the base branch is %A (standard 'merge commit')
|
||||||
|
# ifcmerge_ours — use when the base branch is %B (rebase direction);
|
||||||
|
# swaps the roles so base-branch IDs are still preserved.
|
||||||
|
# Requires ifcmerge to support --prefer-other; if not,
|
||||||
|
# use 'merge commit' strategy exclusively and omit this.
|
||||||
|
|
||||||
|
[merge "ifcmerge"]
|
||||||
|
name = IFC merge driver (base is ours)
|
||||||
|
driver = ifcmerge %O %A %B %L
|
||||||
|
|
||||||
|
[merge "ifcmerge_ours"]
|
||||||
|
name = IFC merge driver (base is theirs)
|
||||||
|
driver = ifcmerge %O %B %A %L
|
||||||
24
forgejo/server-config/ifcurl-preview.service
Normal file
24
forgejo/server-config/ifcurl-preview.service
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
[Unit]
|
||||||
|
Description=ifcurl preview service
|
||||||
|
Documentation=https://github.com/brunopostle/ifcurl
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=ifcurl
|
||||||
|
Group=ifcurl
|
||||||
|
EnvironmentFile=-/etc/ifcurl/env
|
||||||
|
ExecStart=/usr/local/bin/ifcurl serve \
|
||||||
|
--host 127.0.0.1 \
|
||||||
|
--port 8000 \
|
||||||
|
--allowed-hosts git.example.com
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=5
|
||||||
|
|
||||||
|
# Cache configuration — override in /etc/ifcurl/env:
|
||||||
|
# IFCURL_CACHE_MAX_GB=10 max bare-repo disk cache
|
||||||
|
# IFCURL_T2_MAX=8 max IFC blobs in memory
|
||||||
|
# IFCURL_T3_MAX=64 max selector results in memory
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
Loading…
Add table
Reference in a new issue