Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ Dockerfile
**/node_modules/**
docker-compose.yml
docker-compose.dev.yml
docker/.buildx-cache
doc/**
.dockerignore
**/build
Expand Down
8 changes: 1 addition & 7 deletions .github/workflows/docker-release.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
name: Docker Release

# This workflow was largely generated from the following prompt:
# "only run this on merge to main; clone the repo; set the VERSION environment
# variable from packages/runtime/package.json; use `docker manifest inspect`
# to verify the release doesn't already exist; create a multi-platform builder;
# build and push the image"

on:
push:
branches: [main]
Expand All @@ -20,7 +14,7 @@ jobs:
- name: Get version
id: version
run: |
echo "VERSION=$(cat packages/runtime/package.json | jq -r '.version')" >> "$GITHUB_OUTPUT"
echo "VERSION=$(cat packages/compiler/package.json | jq -r '.version')" >> "$GITHUB_OUTPUT"

- name: Check if image already exists
id: check
Expand Down
26 changes: 26 additions & 0 deletions .github/workflows/go-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Go Tests

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
test:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v6

- name: Set up Go
uses: actions/setup-go@v6
with:
go-version-file: go.work

- name: Compile grammar to wasm
run: ./golang/runtime/generate.sh

- name: Run Go tests
working-directory: golang/runtime
run: go test ./...
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,8 @@ yarn-error.log

# api-extractor temp files
temp/

# Docker buildx local layer cache
docker/.buildx-cache

.DS_Store
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,21 @@ You can use the Ohm CLI without a local Node.js installation via the Docker imag
docker run --rm -v $(pwd):/local ohmjs/ohm:latest compile my-grammar.ohm
```

The `compile` command also supports:

- **A separate output directory** — mount it at `/dst` and output paths resolve there:

```sh
docker run --rm -v $(pwd)/src:/local -v $(pwd)/dst:/dst \
ohmjs/ohm:latest compile my-grammar.ohm
```

- **Stdin / stdout streaming** — pass `-` as the grammar file to read from stdin; output goes to stdout:

```sh
cat my-grammar.ohm | docker run --rm -i ohmjs/ohm:latest compile - > my-grammar.wasm
```

For full usage instructions, including how to build the image locally and set up a development container, see [doc/docker.md](doc/docker.md).

### Installation
Expand Down
55 changes: 48 additions & 7 deletions doc/docker.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,34 @@ Options:
docker run --rm -v $(pwd):/local ohmjs/ohm:latest compile -o arithmetic.wasm arithmetic.ohm
```

### Separate input and output directories

Mount a second volume at `/dst` to send the compiled `.wasm` to a different directory than the grammar source. When `/dst` is present, output paths are resolved relative to `/dst`:

```sh
docker run --rm \
-v /path/to/src:/local \
-v /path/to/dst:/dst \
ohmjs/ohm:latest compile grammar.ohm
# writes /path/to/dst/grammar.wasm
```

If `-o` is given as a relative path it is also resolved against `/dst`; absolute paths are used as-is.

### Reading from stdin / writing to stdout

Use `-` as the grammar file to read the grammar from stdin. Use `-o -` (or omit `-o` when reading from stdin) to write the wasm bytes to stdout:

```sh
# pipe grammar in, capture wasm out
cat grammar.ohm | docker run --rm -i ohmjs/ohm:latest compile - > grammar.wasm

# explicit stdout
docker run --rm -i -v $(pwd):/local ohmjs/ohm:latest compile -o - grammar.ohm > grammar.wasm
```

In stdout mode, the CLI's status messages are redirected to stderr so stdout contains only the wasm bytes.

### Getting help

```sh
Expand Down Expand Up @@ -80,6 +108,10 @@ Clone the repository and build the production image with Docker Compose:
git clone https://github.com/ohmjs/ohm.git
cd ohm
docker compose -f docker/docker-compose.yml build

# or
cd ohm/docker
docker compose build
```

This builds the `ohm:latest` image using the `dist` stage of the multi-stage `Dockerfile`, which produces a slim image containing only the compiled packages and their production dependencies.
Expand Down Expand Up @@ -110,16 +142,16 @@ The `-v $(pwd):/local` mount makes your current directory available at `/local`

The `ohm-dev:latest` images is 1.62 GB and is 97% efficient with only 64 MB potentially wasted space.

### Publishing to Docker Hub
### Publishing to Docker Hub (from development machine)

**Note: it is perferable to have the gha docker-release.yml do this**
But there can be a chicken and egg situation where it is easier to do this from a development machine.

Build and push a versioned image to Docker Hub using the git tag as the version:

```sh
# if not set default to ohmjs (ie docker hub using the ohmjs org)
export DOCKER_REPO=<custom docker repo>
# if not set defaults to 'development'
export VERSION=$(cat packages/runtime/package.json | jq -r '.version')
# or export VERSION=$(git describe --tag --dirty)

# # it might be necessary (particularly on osx) to create a new builder
# # the default builder might not support multi-platform builds
Expand All @@ -129,14 +161,23 @@ export VERSION=$(cat packages/runtime/package.json | jq -r '.version')
# # or if already created
# docker buildx use ohmjs-builder

# generate a person access token at https://app.docker.com/accounts/millergarym/settings/personal-access-tokens
# generate a person access token at https://app.docker.com/accounts/<github username>/settings/personal-access-tokens
# assuming DHPAT contains your PAT
echo $DHPAT | docker login -u <personal username> --password-stdin
cd docker
docker buildx bake --allow=fs.read=.. --push
# if not set defaults to 'development'
export VERSION=$(cat ../packages/compiler/package.json | jq -r '.version')
docker buildx use ohmjs-builder
docker buildx bake \
--set="*.cache-from=type=local,src=.buildx-cache" \
--set="*.cache-to=type=local,dest=.buildx-cache,mode=max" \
--allow=fs.read=.. \
--push
```

`git describe --tag --dirty` produces a version string based on the nearest git tag, appending commit info and a `-dirty` suffix if there are uncommitted changes.
Builds use a local layer cache stored in `docker/.buildx-cache`.
On subsequent runs this avoids re-downloading base layers and reinstalling dependencies.
Note the `docker/.buildx-cache` directory is over 1GB, and needs to be cleaned up manually.

The defaults in `docker-compose.yml` are `DOCKER_REPO=ohmjs` and `VERSION=development`. See [docker-compose.yml](../docker/docker-compose.yml) for details.

Expand Down
Loading
Loading