Some checks are pending
release / release (push) Waiting to run
The pinned `opam install dune.3.14.0` failed. setup-ocaml installs a dune of its own for caching, so requesting an exact older version is a downgrade the solver refuses — which also means run 1's `dune: command not found` was only ever a PATH problem, fixed by `opam exec --`. - probe with `opam exec -- dune --version`, install only if absent - echo the resolved version so the log says what built the release - any dune >= 3.14 satisfies `(lang dune 3.14)` Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
139 lines
5.7 KiB
YAML
139 lines
5.7 KiB
YAML
# NOTE: this workflow has never run. Authored 2026-08-25 and not
|
|
# executable locally — the first real tag push is its first test.
|
|
# Expect to adjust the toolchain step if the pinned OCaml/dune version
|
|
# is not available on the runner image.
|
|
|
|
name: release
|
|
|
|
# Fires only on a version tag, so nothing is published by an ordinary
|
|
# push. `workflow_dispatch` is a DRY RUN: it builds, verifies and reports
|
|
# the glibc floor, but skips the tag guard (there is no tag) and skips
|
|
# publishing. Use it to rehearse before tagging anything.
|
|
on:
|
|
push:
|
|
tags:
|
|
- 'v*'
|
|
workflow_dispatch:
|
|
|
|
# The ONE line that replaces `gh auth login`: it widens the automatic
|
|
# GITHUB_TOKEN so this job may write releases. No PAT, no secret to
|
|
# rotate, and the token dies with the job.
|
|
permissions:
|
|
contents: write
|
|
|
|
jobs:
|
|
release:
|
|
# DELIBERATE, not a default. The release binaries link glibc
|
|
# dynamically, so the build host's glibc caps which symbol versions
|
|
# they can import — and that cap becomes the minimum glibc every
|
|
# user needs. Built on 24.04 (glibc 2.39) the floor is 2.39;
|
|
# built here on 22.04 (2.35) it is 2.35, which is the difference
|
|
# between excluding and including Ubuntu 22.04, Debian 12 and
|
|
# RHEL 9. Raise this image only with a reason, and update the
|
|
# supported-systems list in docs/examples/site/install/view.wo in
|
|
# the same change.
|
|
runs-on: ubuntu-22.04
|
|
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
# setup-ocaml gives a compiler and opam. It does NOT give dune —
|
|
# dune is an ordinary opam package, and this project has no .opam
|
|
# file for it to infer one from, so nothing pulls it in. The first
|
|
# run failed here with `dune: command not found`.
|
|
- uses: ocaml/setup-ocaml@v3
|
|
with:
|
|
ocaml-compiler: '4.14'
|
|
|
|
# setup-ocaml may already have installed a dune (it uses one for its
|
|
# own cache), in which case asking for an exact older version is a
|
|
# DOWNGRADE the solver refuses — which is how the pinned
|
|
# `dune.3.14.0` failed. So: use whatever is there, and only install
|
|
# if there is nothing. Any dune >= 3.14 satisfies this project's
|
|
# `(lang dune 3.14)`.
|
|
- name: Ensure dune is available
|
|
run: |
|
|
opam exec -- dune --version || opam install -y dune
|
|
echo "dune: $(opam exec -- dune --version)"
|
|
|
|
# The tag is the release's identity; VERSION is what the binaries
|
|
# report. If they disagree the download URL would name a version
|
|
# nobody can install. mkdist.sh already guards VERSION against the
|
|
# binaries; this guards the tag against VERSION.
|
|
- name: Tag must match VERSION
|
|
if: github.event_name == 'push'
|
|
run: |
|
|
tag="${GITHUB_REF_NAME#v}"
|
|
ver="$(cat VERSION)"
|
|
[ "$tag" = "$ver" ] || {
|
|
echo "tag $GITHUB_REF_NAME does not match VERSION $ver" >&2
|
|
exit 1
|
|
}
|
|
|
|
# `opam exec --` because mkdist.sh calls dune internally; without
|
|
# the opam environment on PATH the script cannot find it.
|
|
- name: Build the tarball
|
|
run: opam exec -- ./scripts/mkdist.sh
|
|
|
|
# The site links one exact filename. If mkdist ever changes its
|
|
# naming, the download button 404s for every visitor — so fail
|
|
# here instead.
|
|
- name: Asset name must match what the site links
|
|
run: |
|
|
ver="$(cat VERSION)"
|
|
asset="writeonce-${ver}-linux-amd64.tar.gz"
|
|
test -f "dist/$asset"
|
|
grep -q "$asset" docs/examples/site/install/view.wo || {
|
|
echo "$asset is not the filename /install links" >&2
|
|
exit 1
|
|
}
|
|
|
|
- name: Verify the digest
|
|
run: cd dist && sha256sum -c "writeonce-$(cat ../VERSION)-linux-amd64.tar.gz.sha256"
|
|
|
|
# Prove the ARTEFACT works, using the binaries inside it rather
|
|
# than the ones just built in the tree. This is what catches a
|
|
# tarball that packaged the wrong thing.
|
|
- name: Smoke-test the extracted toolchain
|
|
run: |
|
|
ver="$(cat VERSION)"
|
|
tmp="$(mktemp -d)"
|
|
tar -C "$tmp" -xzf "dist/writeonce-${ver}-linux-amd64.tar.gz"
|
|
export PATH="$tmp/writeonce/bin:$PATH"
|
|
woc version
|
|
wovm --version
|
|
mkdir -p "$tmp/hello"
|
|
cd "$tmp/hello"
|
|
printf 'name = "hello"\nversion = "0.1.0"\n\n[runtime]\nwo = ">= 0.1"\n' > wo.toml
|
|
printf 'fn main() -> Int {\n print("hello, writeonce");\n return 0;\n}\n' > main.wo
|
|
woc .
|
|
out="$(./target/hello)"
|
|
[ "$out" = "hello, writeonce" ] || { echo "got: $out" >&2; exit 1; }
|
|
|
|
# Record the real glibc floor of what is about to ship, so the
|
|
# claim on /install can be checked against a build log rather
|
|
# than trusted.
|
|
- name: Report the glibc floor
|
|
run: |
|
|
ver="$(cat VERSION)"
|
|
tmp="$(mktemp -d)"
|
|
tar -C "$tmp" -xzf "dist/writeonce-${ver}-linux-amd64.tar.gz"
|
|
for b in "$tmp"/writeonce/bin/*; do
|
|
printf '%s needs %s\n' "$(basename "$b")" \
|
|
"$(objdump -T "$b" | grep -oE 'GLIBC_[0-9.]+' | sort -uV | tail -1)"
|
|
done
|
|
|
|
# gh is preinstalled on GitHub runners and reads GH_TOKEN from the
|
|
# environment, so there is no `gh auth login` anywhere in this file.
|
|
# Skipped on workflow_dispatch: a dry run must never publish.
|
|
- name: Publish
|
|
if: github.event_name == 'push'
|
|
env:
|
|
GH_TOKEN: ${{ github.token }}
|
|
run: |
|
|
ver="$(cat VERSION)"
|
|
gh release create "$GITHUB_REF_NAME" \
|
|
"dist/writeonce-${ver}-linux-amd64.tar.gz" \
|
|
"dist/writeonce-${ver}-linux-amd64.tar.gz.sha256" \
|
|
--title "writeonce ${ver}" \
|
|
--generate-notes
|