Bundle

NAME

App::Ariza::Bundle - build one self-contained archive of an application

SYNOPSIS


use App::Ariza::Bundle;

my %b = App::Ariza::Bundle.build(
    :app-dir('/Users/me/code/App-Moneymoor'),
    :out-dir('/tmp/dist'),
);

say %b<name>;            # moneymoor-0.2.0-macos-arm64
say %b<archive>;         # /tmp/dist/moneymoor-0.2.0-macos-arm64.tar.gz
say %b<sha256>;
say %b<compressed>;      # 76_226_140
say %b<uncompressed>;    # 214_913_002

# Cross-target: a Linux bundle needs a Linux SQLCipher, which this
# machine's package manager cannot supply.
App::Ariza::Bundle.build(
    :app-dir($app), :platform<linux-x86_64-glibc>,
    :sqlcipher-archive('/tmp/libsqlcipher-linux-x86_64.tar.gz'));

DESCRIPTION

The orchestrator. Everything a bundle needs is done by another module in this distribution; this one decides the order, names the artefact, and writes the three files that describe what was made.

The order, and why it is that order

  • App::Ariza::Rakudo unpacks the pinned runtime into < <work>/rakudo >. It goes first because everything after it runs under that runtime.

  • App::Ariza::Site installs the app and its closure into the runtime's own vendor repository — < <work>/rakudo/share/perl6/vendor >, which is the only kind of place a warm precompilation store survives being moved to another machine — using the runtime's own zef, stages notcurses into < <work>/native > as a side effect, and warms that store.

  • App::Ariza::Native stages SQLCipher, then audits every native binary in the bundle. The audit runs after both staging steps because it is a statement about the finished bundle, not about any one component.

  • App::Ariza::Launcher writes < <work>/bin/<exec> > and stages the compiled Windows runner, last, because it needs the target App::Ariza::Site discovered and the library path App::Ariza::Native chose.

  • App::Ariza::Licensing then reads the finished bundle — every native pack's licensing kit, every installed distribution's metadata — and writes THIRD-PARTY.md and LICENSES/. It runs before the manifest because the manifest records its summary, and a summary written after the fact is one that can disagree with the document beside it.

Then VERSION and ariza-manifest.json are written and the whole directory is tarred.

The artefact


<out-dir>/moneymoor-0.2.0-macos-arm64/          # the bundle, left in place
<out-dir>/moneymoor-0.2.0-macos-arm64.tar.gz    # the thing you publish
<out-dir>/moneymoor-0.2.0-macos-arm64.tar.gz.sha256

The archive holds exactly one top-level directory, named after the bundle, so unpacking it anywhere is predictable and never scatters files into the current directory. The checksum file uses the < <hex> <file> > shape shasum -c and sha256sum -c read.

The unpacked workdir is deliberately not deleted: it is what ariza smoke can be pointed at without a round-trip through tar, and what you look inside when something is wrong.

What is inside


bin/moneymoor              the launcher, and the only thing a user runs
rakudo/                    the interpreter (plus SQLCipher, on macOS)
  share/perl6/vendor/      every Raku module, with warm bytecode
native/                    notcurses and friends
VERSION                    one screen: app version and component pins
ariza-manifest.json        the machine-readable version of the same
THIRD-PARTY.md             every component, its licence and where that
                           fact came from
LICENSES/                  the text of every licence the above cites

VERSION and the manifest

VERSION is for a human in a bug report: the app, the platform, and one line per pinned component. ariza-manifest.json is the same facts plus the ones only a machine cares about — every source URL, every SHA-256, every Raku distribution installed with its version and author, and the smoke commands, so ariza smoke can check an archive it knows nothing else about.

THIRD-PARTY.md and LICENSES/

A bundle redistributes other people's software, so it says so — in one document listing every component with its version, its licence, its copyright and where that fact came from, and one directory holding the text of every licence it cites.

None of it is written down in ariza. App::Ariza::Licensing reads a native pack's own licensing kit, ariza's maintained data file for the vendored runtime and MoarVM's vendored C libraries, the license field of every distribution installed into the bundle, and the app's ariza.toml. A component it cannot attribute is a visible row and a warning rather than a silence, and licensing.strict in the app's config turns that into a failed build.

Declared platforms are enforced

Building a slug the app does not list in bundle.platforms is an error. An app that lists its platforms has made a statement about which ones it is tested on, and producing an artefact named <app>-<ver>-<slug> for one it never claimed is a promise ariza has no business making on its behalf. An app with no bundle.platforms at all imposes no such constraint.

METHODS

build(:$app-dir!, :$platform, :$out-dir, :$sqlcipher-archive, :$verbose --> Hash)

The whole build. :$platform defaults to this machine's slug; :$out-dir to the current directory; :$sqlcipher-archive stages a local SQLCipher archive instead of taking the machine's own copy, which is what a cross-build or an air-gapped build needs.

Returns name, dir, archive, checksum, sha256, compressed, uncompressed, manifest, launchers, audit, licensing, platform and version.

bundle-name(:$exec!, :$version!, :$platform! --> Str)

< <exec>-<version>-<platform> > — the workdir name and the archive stem.

version-file(%manifest --> Str)

The text of VERSION, rendered from a manifest. Public because it is the one artefact whose exact wording a human reads in a bug report, and because rendering it is worth testing without building 165MB first.

runner-component(%runner, IO::Path $work --> Hash)

The manifest's components.runner entry: the published artefact that was staged, the release it came from, its URL and the digest it was verified against. The runner is downloaded like the runtime archive is, so it is recorded like the runtime archive is — without this it would be the one binary in a bundle a reader could not trace back to something published, which for the file a Windows user actually runs is the worst place to have a gap.

notcurses-component(%site --> Hash)

The manifest's Notcurses tag and exact staged lib/ directory from App::Ariza::Site. Windows launchers and smoke consume the same path; reconstructing it independently would let metadata and the live loader contract drift apart.

sqlcipher-component(%sqlcipher --> Hash)

The manifest's components.sqlcipher entry, built from what App::Ariza::Native staged: the version staged (or 'unknown'), the pinned one beside it, the bundle-relative path, the digest, and the provenance sentence. Public because "does the manifest tell the truth about what was bundled" is worth a test that does not build 165MB first.

app-version(IO() $app-dir --> Str)

The version from the checkout's META6.json. Read from source rather than from the installed distribution because the workdir has to be named before anything is installed.

SEE ALSO

App::Ariza::Smoke, which takes the archive this produces and proves it runs somewhere else.

AUTHOR

Matt Doughty

COPYRIGHT AND LICENSE

Copyright 2026 Matt Doughty

This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.

App::Ariza v0.2.4

bundler and distribution tool for Raku terminal apps

Authors

  • Matt Doughty

License

Artistic-2.0

Dependencies

Config::TOML:ver<0.1.3+>:auth<zef:raku-community-modules>JSON::Fast:ver<0.19+>:auth<cpan:TIMOTIMO>Template::Jinja2:ver<0.3.0+>:auth<zef:apogee>

Test Dependencies

Provides

  • App::Ariza
  • App::Ariza::Bundle
  • App::Ariza::CI
  • App::Ariza::Config
  • App::Ariza::Installer
  • App::Ariza::Launcher
  • App::Ariza::Licensing
  • App::Ariza::Native
  • App::Ariza::Platform
  • App::Ariza::Rakudo
  • App::Ariza::Resources
  • App::Ariza::Runner
  • App::Ariza::Site
  • App::Ariza::Smoke
  • App::Ariza::Tools
  • App::Ariza::Update
  • App::Ariza::Versions

The Camelia image is copyright 2009 by Larry Wall. "Raku" is a trademark of the Yet Another Society. All rights reserved.

Built with Podlite — the markup and publishing tools behind this site.