Skip to content

Commit 74b7dd2

Browse files
committed
brew and CI/CD update
1 parent 8c8c6fe commit 74b7dd2

14 files changed

Lines changed: 425 additions & 22 deletions

File tree

.github/workflows/maven.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ jobs:
1212
runs-on: ubuntu-latest
1313

1414
steps:
15-
- uses: actions/checkout@v4
15+
- uses: actions/checkout@v5
1616
- name: Set up JDK 25
17-
uses: actions/setup-java@v4
17+
uses: actions/setup-java@v5
1818
with:
1919
java-version: '25'
2020
distribution: 'temurin'

.github/workflows/packaging.yml

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ jobs:
1111
matrix:
1212
os: [ ubuntu-latest, windows-latest, macos-latest, macos-15-intel ]
1313
steps:
14-
- uses: actions/checkout@v4
14+
- uses: actions/checkout@v5
1515

1616
- name: Set up JDK 25
17-
uses: actions/setup-java@v4
17+
uses: actions/setup-java@v5
1818
with:
1919
java-version: '25'
2020
distribution: oracle
@@ -32,23 +32,23 @@ jobs:
3232
# Linux upload Application
3333
- name: Upload Linux Package Application
3434
if: matrix.os == 'ubuntu-latest'
35-
uses: actions/upload-artifact@v4.6.2
35+
uses: actions/upload-artifact@v5
3636
with:
3737
name: linux-x64
3838
path: ./cli/output/*.deb
3939

4040
# Linux upload Language Server
4141
- name: Upload Linux Package Language Server
4242
if: matrix.os == 'ubuntu-latest'
43-
uses: actions/upload-artifact@v4.6.2
43+
uses: actions/upload-artifact@v5
4444
with:
4545
name: lsp-linux-x64
4646
path: ./lsp/output/*.deb
4747

4848
# Windows upload Application
4949
- name: Upload Windows Package Application
5050
if: matrix.os == 'windows-latest'
51-
uses: actions/upload-artifact@v4.6.2
51+
uses: actions/upload-artifact@v5
5252
with:
5353
name: windows-x64
5454
path: |
@@ -58,7 +58,7 @@ jobs:
5858
# Windows upload Language Server
5959
- name: Upload Windows Package Language Server
6060
if: matrix.os == 'windows-latest'
61-
uses: actions/upload-artifact@v4.6.2
61+
uses: actions/upload-artifact@v5
6262
with:
6363
name: lsp-windows-x64
6464
path: |
@@ -68,31 +68,31 @@ jobs:
6868
# macOS upload Application
6969
- name: Upload macOS Package Application
7070
if: matrix.os == 'macos-latest'
71-
uses: actions/upload-artifact@v4.6.2
71+
uses: actions/upload-artifact@v5
7272
with:
7373
name: macos-arm64
7474
path: ./cli/output/*.pkg
7575

7676
# macOS upload Language Server
7777
- name: Upload macOS Package Language Server
7878
if: matrix.os == 'macos-latest'
79-
uses: actions/upload-artifact@v4.6.2
79+
uses: actions/upload-artifact@v5
8080
with:
8181
name: lsp-macos-arm64
8282
path: ./lsp/output/*.pkg
8383

8484
# macOS Intel upload Application
8585
- name: Upload macOS Package Application
8686
if: matrix.os == 'macos-15-intel'
87-
uses: actions/upload-artifact@v4.6.2
87+
uses: actions/upload-artifact@v5
8888
with:
8989
name: macos-x64
9090
path: ./cli/output/*.pkg
9191

9292
# macOS Intel upload Language Server
9393
- name: Upload macOS Package Language Server
9494
if: matrix.os == 'macos-15-intel'
95-
uses: actions/upload-artifact@v4.6.2
95+
uses: actions/upload-artifact@v5
9696
with:
9797
name: lsp-macos-x64
9898
path: ./lsp/output/*.pkg

BREW.md

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
# Turicum Homebrew Packaging
2+
3+
*Status: implemented and verified locally, 2026-07-17, for release 1.4.2. One
4+
publishing step remains open — pushing the tap repository to GitHub, see §5.*
5+
6+
This document records how the Homebrew packaging of the Turicum CLI works, what
7+
was set up, what state exists on the development machine, and what to do on
8+
every release. The operational short version lives in `homebrew/README.md`;
9+
this is the full description.
10+
11+
## 1. Design: what gets installed, from where
12+
13+
The packaging deliberately builds **nothing**. Every Maven release already
14+
publishes a self-contained CLI distribution to Maven Central:
15+
16+
https://repo1.maven.org/maven2/ch/turic/turicum-cli/<version>/turicum-cli-<version>-distribution.zip
17+
18+
The zip is produced by `cli/src/main/assembly/bin.xml` (maven-assembly-plugin,
19+
`dist` execution) and contains exactly three flat jars:
20+
21+
| Jar | Role |
22+
|---|---|
23+
| `turicum-cli-<version>.jar` | the CLI, entry point `ch.turic.cli.Main` |
24+
| `turicum-<version>.jar` | the core interpreter |
25+
| `jline-<version>.jar` | terminal handling for the REPL |
26+
27+
Maven Central serves an official `.sha256` next to the artifact, which is what
28+
the formula pins. The Homebrew formula:
29+
30+
1. downloads the zip (the formula uses the `search.maven.org/remotecontent`
31+
form of the URL because `brew audit` prefers it; it serves the identical
32+
file as `repo1.maven.org`);
33+
2. installs the three jars into the formula's `libexec` (so they are not on
34+
anyone's classpath by accident);
35+
3. writes a `turi` wrapper script into `bin`:
36+
37+
```bash
38+
#!/bin/bash
39+
exec "<openjdk>/bin/java" -cp "<libexec>/*" ch.turic.cli.Main "$@"
40+
```
41+
42+
The explicit `-cp` glob is needed because the cli jar has no `Main-Class`
43+
manifest entry. The wrapper runs on Homebrew's `openjdk` formula
44+
(dependency), so users do not need their own Java; Turicum needs Java 21+
45+
and the Homebrew `openjdk` is always newer than that.
46+
47+
The command is called **`turi`**, matching the `.turi` source-file extension:
48+
49+
turi program.turi # run a program
50+
turi -REPL # interactive REPL
51+
turi -compile x.turi # compile to .turc
52+
turi -version
53+
turi -help
54+
55+
## 2. Files in this repository
56+
57+
Everything lives under `homebrew/`:
58+
59+
| File | Purpose |
60+
|---|---|
61+
| `homebrew/turicum.rb` | The formula. Clean under `brew style` and `brew audit --strict`. Carries a `livecheck` block (Maven Central `maven-metadata.xml`) and a `test do` block that runs a one-line program and checks `turi -version`. |
62+
| `homebrew/update-formula.sh` | Release helper: determines the latest release from Maven Central (or takes a version argument), fetches Central's official sha256, verifies it by downloading and hashing the artifact, and rewrites the formula's `url`/`sha256` lines in place. Before bumping, it snapshots the outgoing version as a versioned formula `turicum@<oldversion>.rb` (see §7). |
63+
| `homebrew/README.md` | Short operational readme: install, publish as tap, release steps. |
64+
65+
Formula details worth remembering:
66+
67+
- There is **no explicit `version` line** — brew scans the version from the
68+
URL, and an explicit line is flagged as redundant by `brew audit --strict`.
69+
`update-formula.sh` therefore only rewrites `url` and `sha256`.
70+
- The file starts with `# typed: strict` / `# frozen_string_literal: true` and
71+
a class documentation comment — all required by `brew style`.
72+
- `desc` must not start with the formula name (another style rule), hence
73+
"Programming language: interpreter, compiler, and REPL".
74+
75+
## 3. The tap
76+
77+
Homebrew 6 refuses to install a formula from a bare file path
78+
(`Error: Homebrew requires formulae to be in a tap`), so distribution happens
79+
through a **tap** — a git repository named `homebrew-<name>` on GitHub.
80+
81+
The tap was created locally with `brew tap-new verhas/tap`. It lives at:
82+
83+
$(brew --repository)/Library/Taps/verhas/homebrew-tap
84+
85+
It is a normal git repository, scaffolded by brew with standard CI workflows
86+
(`.github/workflows/tests.yml`, `publish.yml` for test-bot/bottling — usable
87+
later, ignorable for now), and contains the formula as
88+
`Formula/turicum.rb`, committed as "turicum 1.4.2 (new formula)".
89+
90+
The formula exists in two places by design: `homebrew/turicum.rb` in this repo
91+
is the **source of truth** that is versioned and updated together with
92+
Turicum; the tap's `Formula/turicum.rb` is the **published copy**. Every
93+
release copies the former over the latter (§6).
94+
95+
## 4. What was verified (2026-07-17)
96+
97+
- `brew style homebrew/turicum.rb` — no offenses.
98+
- `brew audit --strict verhas/tap/turicum` — no problems.
99+
- `brew install verhas/tap/turicum` — installs; `which turi`
100+
`/opt/homebrew/bin/turi`.
101+
- `turi -version` → "Turicum Version 1.4.2 (Built: 2026-06-02…)".
102+
- A hello-world `.turi` program runs.
103+
- `brew test turicum` — passes (runs the formula's `test do` block).
104+
- The sha256 in the formula equals Maven Central's official
105+
`…distribution.zip.sha256` **and** the locally computed hash of the
106+
downloaded artifact:
107+
`c766df5cc426fd8511f6e36c5b5ec3d59fe0690587864b3dac50e665401a9c3c`.
108+
109+
`turi` 1.4.2 is installed on this machine through the local tap
110+
(`brew uninstall turicum` removes it).
111+
112+
## 5. Remaining step: publish the tap (one-time)
113+
114+
1. Create the GitHub repository **`verhas/homebrew-tap`** (public).
115+
2. Push the local tap repo to it:
116+
117+
```sh
118+
cd "$(brew --repository)/Library/Taps/verhas/homebrew-tap"
119+
git remote add origin git@github.com:verhas/homebrew-tap.git
120+
git push -u origin main
121+
```
122+
123+
From then on, anyone installs Turicum with:
124+
125+
```sh
126+
brew install verhas/tap/turicum
127+
```
128+
129+
(`brew` expands `verhas/tap` to `github.com/verhas/homebrew-tap` and taps it
130+
automatically.) Worth adding to `README.adoc` as the macOS/Linux install
131+
instruction once the tap is public.
132+
133+
## 6. Per-release workflow
134+
135+
This is step "Homebrew" of the overall release process described in
136+
`RELEASE.md`. After a normal Maven release has reached Maven Central:
137+
138+
```sh
139+
homebrew/update-formula.sh # or: homebrew/update-formula.sh 1.4.3
140+
brew style homebrew/*.rb # lint the bumped and the snapshot formula
141+
cp homebrew/turicum.rb homebrew/turicum@*.rb \
142+
"$(brew --repository)/Library/Taps/verhas/homebrew-tap/Formula/"
143+
brew reinstall turicum # smoke-test the new version locally
144+
brew test turicum
145+
cd "$(brew --repository)/Library/Taps/verhas/homebrew-tap"
146+
git add Formula && git commit -m "turicum <version>"
147+
git push
148+
```
149+
150+
Also commit the updated/added formulae under `homebrew/` in this repository.
151+
152+
`brew livecheck turicum` compares the formula against Maven Central's
153+
`<release>` metadata and reports when the formula lags a release.
154+
155+
## 7. Multiple installable versions
156+
157+
Homebrew's model is one formula file per installable version: `turicum.rb`
158+
always tracks the latest release, and *versioned formulae* named
159+
`turicum@<version>.rb` keep specific older releases installable:
160+
161+
```sh
162+
brew install verhas/tap/turicum # latest
163+
brew install verhas/tap/turicum@1.4.2 # pinned older release
164+
```
165+
166+
`update-formula.sh` creates these automatically: on every bump it snapshots
167+
the outgoing version first (skipping the snapshot if the file already
168+
exists). A versioned formula differs from the main one in three ways:
169+
170+
- file and class name: `turicum@1.4.2.rb` must contain class `TuricumAT142`
171+
(brew's mapping: `@``AT`, dots dropped);
172+
- no `livecheck` block — a pinned version has nothing to check;
173+
- `keg_only :versioned_formula` — pinned versions install but do not link
174+
`turi` into the PATH, so any number of them can coexist with the main
175+
formula. A pinned version is run via
176+
`$(brew --prefix turicum@1.4.2)/bin/turi`, or force-linked with
177+
`brew link --overwrite turicum@1.4.2` after unlinking the others.
178+
179+
Versions that predate the snapshot mechanism remain recoverable from the
180+
tap's git history with `brew extract turicum verhas/tap --version=<v>`, which
181+
generates the corresponding `turicum@<v>.rb` from a past commit. Users who
182+
only want to stop upgrading need none of this: `brew pin turicum` blocks
183+
upgrades until unpinned.
184+
185+
## 8. Possible future improvements
186+
187+
- **Automate the release bump**: a GitHub Actions workflow in the tap repo
188+
(scheduled, or triggered by the Turicum release) that runs the equivalent of
189+
`update-formula.sh`, commits, and pushes. Not set up yet.
190+
- **Bottles**: the tap scaffolding contains brew's test-bot workflows; since
191+
the formula only unpacks jars and writes a script, bottling brings little —
192+
installation is already fast — but it removes the Java-less install-time
193+
dependency on curl reaching Maven Central.
194+
- **`brew install turicum` without the tap prefix** would require acceptance
195+
into homebrew-core; their bar (notability, no pre-built binaries policy
196+
exceptions for Java are common, though — many Java tools ship jars) can be
197+
attempted once the language has more users.

cli/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2-
<!-- Generated on: 2026-07-17T15:55:04.205824+02:00[Europe/Budapest] -->
2+
<!-- Generated on: 2026-07-17T17:19:42.435749+02:00[Europe/Budapest] -->
33
<!-- Generated by: turicum maven extension -->
44
<!-- Do not modify this file. Edit the 'pom.turi' instead -->
55
<project>

clifx/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2-
<!-- Generated on: 2026-07-17T15:55:04.22183+02:00[Europe/Budapest] -->
2+
<!-- Generated on: 2026-07-17T17:19:44.057415+02:00[Europe/Budapest] -->
33
<!-- Generated by: turicum maven extension -->
44
<!-- Do not modify this file. Edit the 'pom.turi' instead -->
55
<project>

core/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2-
<!-- Generated on: 2026-07-17T15:55:04.110282+02:00[Europe/Budapest] -->
2+
<!-- Generated on: 2026-07-17T17:19:38.240243+02:00[Europe/Budapest] -->
33
<!-- Generated by: turicum maven extension -->
44
<!-- Do not modify this file. Edit the 'pom.turi' instead -->
55
<project>
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
let `turicum.version` = "1.4.2";
1+
let `turicum.version` = "2.0.0";
22

33
export_all();

homebrew/README.md

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# Installing Turicum with Homebrew
2+
3+
*This is the short operational readme; the full description of the packaging —
4+
design, tap layout, verification record, release workflow — is in
5+
[`../BREW.md`](../BREW.md).*
6+
7+
This directory contains the Homebrew packaging of the Turicum command-line
8+
interpreter. The formula does not build anything: it downloads the released
9+
`turicum-cli-<version>-distribution.zip` from Maven Central (the artifact the
10+
normal Maven release already publishes, with its official sha256), installs the
11+
three jars into the formula's `libexec`, and creates a `turi` wrapper script in
12+
`bin` that starts `ch.turic.cli.Main` on the Homebrew-managed JDK.
13+
14+
## Installing directly from a checkout
15+
16+
```sh
17+
brew install ./homebrew/turicum.rb
18+
turi -version
19+
turi -REPL
20+
```
21+
22+
## Publishing as a tap (the `brew install verhas/tap/turicum` experience)
23+
24+
Homebrew distributes third-party formulae through *taps*: GitHub repositories
25+
named `homebrew-<name>`. One-time setup:
26+
27+
1. Create the repository `github.com/verhas/homebrew-tap`.
28+
2. Copy the formula into it as `Formula/turicum.rb` and push.
29+
30+
Users then install with:
31+
32+
```sh
33+
brew install verhas/tap/turicum
34+
```
35+
36+
(`brew` expands `verhas/tap` to `github.com/verhas/homebrew-tap` and taps it
37+
automatically.)
38+
39+
## Releasing a new version
40+
41+
After a normal Maven release reaches Maven Central:
42+
43+
```sh
44+
homebrew/update-formula.sh # picks up the latest release automatically
45+
# or: homebrew/update-formula.sh 1.4.3
46+
brew style homebrew/*.rb # lint
47+
brew reinstall turicum # smoke-test locally (after copying to the tap)
48+
brew test turicum
49+
```
50+
51+
Besides bumping `turicum.rb`, the script snapshots the **outgoing** version as
52+
a versioned formula `turicum@<oldversion>.rb` (class `TuricumAT<digits>`, no
53+
`livecheck`, `keg_only :versioned_formula`), so earlier releases stay
54+
installable with `brew install verhas/tap/turicum@<version>`. Being keg-only,
55+
a pinned version does not link `turi` into the PATH; run it via
56+
`$(brew --prefix turicum@<version>)/bin/turi`.
57+
58+
Copy the updated `turicum.rb` **and** the new `turicum@…rb` into the tap
59+
repository's `Formula/` directory and push. The main formula also carries a
60+
`livecheck` block, so `brew livecheck turicum` reports when Maven Central has
61+
a newer release than the formula.
62+
63+
## Notes
64+
65+
- The formula depends on Homebrew's `openjdk` (Turicum needs Java 21+; the
66+
current openjdk formula is always newer than that). Users do not need their
67+
own Java installation.
68+
- The wrapper is called `turi`, matching the `.turi` source-file extension.
69+
- The `test do` block runs a one-line Turicum program and checks
70+
`turi -version`, so `brew test turicum` verifies a working installation.

0 commit comments

Comments
 (0)