Three composable actions for turning a Julia project into a relocatable Julia
distribution: a self-contained tree holding a Julia runtime, a system image with
the project's dependencies baked into it, and those dependencies exposed as
standard libraries. Someone who unpacks it gets a julia that can start using
the project without resolving, installing or compiling anything.
| Action | What it does |
|---|---|
create-julia-distribution |
Builds the distribution from a project. |
create-julia-distribution/pack |
Packs a built distribution into a gzipped tarball. |
create-julia-distribution/sign-macos |
Signs the Mach-O binaries and bundles in a built macOS distribution. |
An action called "create a Julia distribution" that neither installs Julia nor publishes anything is worth reading as composable rather than as unfinished. It covers the build and nothing around it:
- It does not install Julia. A
juliaonPATHis what the distribution is built with and what determines the runtime version it ships, so installing it is where a caller chooses that version. - It does not set up private registries or hold credentials. Dependencies
resolving from the default registries need nothing, since
PkgprovisionsGeneralitself while instantiating the project. Anything beyond that — a package server, a private registry, an SSH key — is arranged by the caller in a preceding step. No input takes a token. - It does not sign anything. The macOS signing action is a separate call the caller makes on the built tree; signing for other runners, notarization and stapling are the caller's own steps entirely.
- It does not publish anything. Nothing is uploaded, tagged or released; the distribution is left in the workspace for the caller to do something with.
- It does not test the result. The built tree contains a working
julia, and running anything against it is a step the caller adds. - It does not cache your dependencies. Every run resolves and builds from scratch unless the caller arranges a warm depot itself.
Building and packing are two actions rather than one so that the interval between them exists. The build leaves an unpacked directory in the workspace and reports its path; anything done to a distribution — signing it, pruning it, rewriting something in it, measuring it, running a test suite against it — is a step the caller puts in that interval, operating on the tree in place. Packing then turns whatever the tree has become into a tarball.
- uses: "JuliaComputing/create-julia-distribution@958799562b82fcabd2f5508f7ee296e1d91de200" # build
- run: "..." # your steps
- uses: "JuliaComputing/create-julia-distribution/pack@958799562b82fcabd2f5508f7ee296e1d91de200" # packCalling the two back to back with nothing in between is complete and supported; the minimum example does exactly that.
Important
Anything sensitive that a build can reach is at risk during it. Building a system image runs code from the project and its dependencies — precompilation, module initialization and whatever else is evaluated while the image is created — and that code runs with everything the job has: the environment, the filesystem, the network. A token in an environment variable, a credential file an earlier step wrote, a signing key materialized before the build, a cloud credential from an assumed role: a dependency you did not write can read any of it, exfiltrate it, or sign with it.
This is not hypothetical hardening. Building a distribution means executing your whole dependency tree, so treat the build as a place where third-party code runs with your job's privileges, and grant it only what resolving and building genuinely need.
Everything else belongs in the interval after the build, which is where the signing example writes its signing certificate.
- Tutorial — an empty project to a built distribution, from scratch.
- Examples, each a complete workflow:
- Build and pack an unsigned distribution, the minimum, and what you get.
- Bring your own registries and credentials.
- Sign between the build and the pack.
- Customize the build — the precompilation workload, extra files to ship, and a script that runs while the system image is generated.
- Reference for every input and output:
create-julia-distribution,pack,sign-macos. - Limits — what the inputs deliberately do not reach, and what is not configurable at all.