Skip to content
Merged
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
35 changes: 35 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,25 @@ jobs:
# The library crates have no OS dependency and run on the host. The
# parser, the graph, the restart policy, the log format and the calendar
# arithmetic are where the logic errors are.
# `test-demo` builds the image locally and checks it, which is what let
# the README ship a `docker run ghcr.io/...` line pointing at something
# that had never been published: the test and the README were talking
# about different images. This checks they agree on the name, which is
# the half a test on a locally-built image structurally cannot.
- name: The README's image reference is the one CI publishes
run: |
OWNER=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]')
WANT="ghcr.io/$OWNER/oxinit:demo"
if ! grep -qF "$WANT" README.md; then
echo "README.md does not mention $WANT, which is what CI pushes"
exit 1
fi
if ! grep -qF 'oxinit:demo' .github/workflows/ci.yml; then
echo "the publish step no longer pushes the tag the README names"
exit 1
fi
echo "README and CI agree on $WANT"

- name: Host tests
run: cargo test -p oxinit-unit -p oxinit-graph -p oxinit-service -p oxinit-cgroup -p oxinit-user -p oxinit-ipc -p oxinit-log -p oxinit-timer

Expand Down Expand Up @@ -164,6 +183,9 @@ jobs:
name: the README's demo
runs-on: ubuntu-latest
needs: check
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- run: rustup target add x86_64-unknown-linux-musl
Expand All @@ -185,6 +207,19 @@ jobs:
# works is worse than a README with nothing in it.
- run: cargo xtask test-demo

# The demo image is documentation, not a release artifact, so it is
# published from `main` rather than from a tag. Tying it to a release
# meant the README told people to pull something that would not exist
# until a version number had been declared — which is a separate
# decision, and was not going to be made that week.
- name: Publish the demo image
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
run: |
OWNER=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]')
echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
docker tag oxinit:demo "ghcr.io/$OWNER/oxinit:demo"
docker push "ghcr.io/$OWNER/oxinit:demo"

distro:
name: a real userspace
runs-on: ubuntu-latest
Expand Down
18 changes: 13 additions & 5 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,18 +81,20 @@ jobs:
# demo/, not units/ — the latter is the test suite and contains services
# that fail on purpose.
- name: Build the demo image
run: cargo xtask demo --build-only --tag ghcr.io/${{ github.repository_owner }}/oxinit:demo
run: cargo xtask demo --build-only

- name: Log in to ghcr.io
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin

# Only the versioned tag. `:demo` tracks `main` and is published by CI,
# because it is documentation rather than a release artifact — the README
# points at it, and a README should not be waiting on a version number
# somebody has not decided to declare yet.
- name: Push
run: |
OWNER=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]')
docker tag ghcr.io/${{ github.repository_owner }}/oxinit:demo ghcr.io/$OWNER/oxinit:demo
docker tag ghcr.io/$OWNER/oxinit:demo ghcr.io/$OWNER/oxinit:${{ github.ref_name }}
docker push ghcr.io/$OWNER/oxinit:demo
docker push ghcr.io/$OWNER/oxinit:${{ github.ref_name }}
docker tag oxinit:demo "ghcr.io/$OWNER/oxinit:${{ github.ref_name }}"
docker push "ghcr.io/$OWNER/oxinit:${{ github.ref_name }}"

release:
name: publish
Expand Down Expand Up @@ -125,6 +127,12 @@ jobs:
docker run --rm --name oxinit-demo -p 8080:8080 ghcr.io/OWNER/oxinit:TAG
```

`ghcr.io/OWNER/oxinit:demo` tracks `main` if you would rather have the
latest.

```bash
```

### Install

Download the tarball for your architecture below, check it, and put
Expand Down
23 changes: 12 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,17 @@ flowchart TD
That is deliberate: a bug in the log writer kills the log writer, and a bug in
PID 1 kills the machine.

## Try it — one command
## Try it

You need [Docker](https://docs.docker.com/get-started/get-docker/) and nothing
else. No Rust, no virtual machine, no kernel.
You need [Docker](https://docs.docker.com/get-started/get-docker/) and a Rust
toolchain. Two commands:

```bash
cargo xtask fetch --arch x86_64 # a kernel and a busybox, into target/
cargo xtask demo # build the image and run it
```

Or pull the image, which tracks `main` and needs no toolchain at all:

```bash
docker run --rm --name oxinit-demo -p 8080:8080 ghcr.io/youhide/oxinit:demo
Expand Down Expand Up @@ -81,14 +88,8 @@ for each to actually be gone, and exits `0`. Most container images have to be
killed after a ten-second grace period; that shows up as exit code 137.

The units the demo runs are in [demo/](demo/), one small file each, and they
are meant to be read.

To build and run it yourself instead of pulling the published image:

```bash
cargo xtask fetch --arch x86_64 # a kernel and a busybox, into target/
cargo xtask demo # build the image and run it
```
are meant to be read. The image is 4.6 MB — statically linked against musl,
`FROM scratch`, no base image and no shared libraries.

## Why

Expand Down
33 changes: 33 additions & 0 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -963,6 +963,39 @@ twelve seconds later — and the test image asks for a shutdown sixteen seconds
in, inside that window with margin on both sides. Reproducing it by luck once
is not a regression test.

### The first command in the README did not work

Reported by the first person to try it, which is the whole point of writing a
section for people who have not seen the project before — and an unambiguous
failure of the milestone that added it.

The README told a newcomer to `docker run ghcr.io/…/oxinit:demo`. No tag had
been pushed, so the release workflow that published that image had never run,
and the image did not exist. `test-demo` passed the entire time: it builds the
image locally and checks *that*, so the test and the README were talking about
two different images and nothing compared them.

Three fixes, and only one of them is the obvious one.

The demo image is **documentation, not a release artifact**, so it is published
from `main` by CI rather than from a tag by the release workflow. Tying it to a
release meant the README pointed at something that would not exist until a
version number had been declared — a separate decision, and not one anybody was
about to make. The release workflow now adds a versioned tag and nothing else.

The README leads with the two commands that work with no registry at all, and
offers the pull second.

And CI checks that the image reference in the README is the one the publish
step pushes. That is the half a test on a locally built image structurally
cannot cover, and it is the half that failed.

One thing here is not automatable: a package pushed by Actions is **private by
default**, and an anonymous `docker run` against a private package fails with
exactly the `denied` that was reported. Making it public is a one-time setting
on the repository's package page, and it belongs to whoever owns the account
rather than to CI.

## Not doing, and why

These were on the list. They are coming off it with a reason rather than
Expand Down
Loading