Package Examples
A set of `.pkg.lua` examples for creating Zoi packages.
This document provides a set of examples for creating .pkg.lua
files. These files are the core of Zoi's packaging system, defining everything from metadata to installation methods using the power of Lua scripting.
Comprehensive Package Example
This is a comprehensive example that showcases many of Zoi's packaging features. It defines a package with multiple, selectable installation methods, including pre-compiled binaries, compressed archives, an installer script, and building from source, with platform-specific logic.
-- hello.pkg.lua
-- Using local variables to follow DRY principle.
local repo_owner = "Zillowe"
local repo_name = "Hello"
local version = "2.0.0"
local git_url = "https://github.com/" .. repo_owner .. "/" .. repo_name .. ".git"
local release_base_url = "https://github.com/" .. repo_owner .. "/" .. repo_name .. "/releases/download/v" .. version
-- Platform mapping allows customizing OS and architecture names for URLs and filenames.
-- The key is the platform string reported by Zoi (e.g. "macos", "linux-amd64").
-- The value is the desired platform string to be used in the package script.
local platform_map = {
macos = "darwin",
}
local function get_mapped_platform()
local current_platform = SYSTEM.OS .. "-" .. SYSTEM.ARCH
return platform_map[current_platform] or platform_map[SYSTEM.OS] or current_platform
end
local function get_mapped_os()
return get_mapped_platform():match("([^%-]+)")
end
package({
name = "hello",
repo = "zillowe",
version = version,
description = "Hello World",
website = "https://github.com/Zillowe/Hello",
git = git_url,
maintainer = {
name = "Your Name",
email = "[email protected]",
},
author = {
name = "Zillowe Foundation",
website = "https://zillowe.qzz.io",
email = "[email protected]",
key = "https://zillowe.pages.dev/keys/zillowe-main.asc",
key_name = "zillowe-main",
},
license = "Apache-2.0",
bins = { "hello" },
conflicts = { "hello" },
})
install({
selectable = true,
{
name = "Binary",
type = "binary",
url = (function()
return release_base_url .. "/hello-" .. get_mapped_os() .. "-" .. SYSTEM.ARCH
end)(),
platforms = { "all" },
checksums = (function()
return release_base_url .. "/checksums-512.txt"
end)(),
sigs = {
{
file = (function()
return "hello-" .. get_mapped_os() .. "-" .. SYSTEM.ARCH
end)(),
sig = (function()
return release_base_url .. "/hello-" .. get_mapped_os() .. "-" .. SYSTEM.ARCH .. ".sig"
end)(),
},
},
},
{
name = "Compressed Binary",
type = "com_binary",
url = (function()
local ext
if SYSTEM.OS == "windows" then
ext = "zip"
else
ext = "tar.xz"
end
return release_base_url .. "/hello-" .. get_mapped_os() .. "-" .. SYSTEM.ARCH .. "." .. ext
end)(),
platforms = { "all" },
checksums = (function()
return release_base_url .. "/checksums-512.txt"
end)(),
sigs = {
{
file = (function()
local ext
if SYSTEM.OS == "windows" then
ext = "zip"
else
ext = "tar.xz"
end
return "hello-" .. get_mapped_os() .. "-" .. SYSTEM.ARCH .. "." .. ext
end)(),
sig = (function()
local ext
if SYSTEM.OS == "windows" then
ext = "zip"
else
ext = "tar.xz"
end
return release_base_url
.. "/hello-"
.. get_mapped_os()
.. "-"
.. SYSTEM.ARCH
.. "."
.. ext
.. ".sig"
end)(),
},
},
},
{
name = "Install Script",
type = "script",
url = (function()
local ext
if SYSTEM.OS == "windows" then
ext = "ps1"
else
ext = "sh"
end
return "https://raw.githubusercontent.com/Zillowe/Hello/refs/heads/main/app/install." .. ext
end)(),
platforms = { "all" },
},
{
name = "Build from source",
type = "source",
url = git_url,
platforms = { "linux", "macos", "windows" },
build_commands = {
'go build -o hello -ldflags="-s -w" ./src',
},
bin_path = (function() -- the final binary path
local bin
if SYSTEM.OS == "windows" then
bin = "hello.exe"
else
bin = "./hello"
end
return bin
end)(),
files = {
{
platforms = { "linux", "macos" },
files = {
{
source = "README.md",
destination = "/usr/local/share/doc/hello/README.md",
},
},
},
{
platforms = { "windows" },
files = {
{
source = "README.md",
destination = "C:\\ProgramData\\hello\\README.md",
},
},
},
},
},
})
dependencies({
build = {
required = { "native:go" },
},
})
Build from Source Package
For packages that need to be compiled on the user's machine, use the source
installation type.
-- dev/compiler.pkg.lua
package({
name = "compiler",
repo = "community",
version = "0.1.0",
description = "A new programming language compiler.",
git = "https://github.com/user/compiler",
tags = { "compiler", "devtools" },
maintainer = {
name = "Your Name",
email = "[email protected]"
}
})
install({
{
type = "source",
url = PKG.git, -- URL to the git repository.
platforms = { "linux-amd64", "macos-amd64", "windows-amd64" },
-- Optional: build inside a Docker container for reproducibility.
docker_image = "hub:golang:1.21-alpine",
-- Commands to execute in the cloned repository to build.
build_commands = {
"go build -o compiler"
},
-- Path to the built binary, relative to the repo root.
-- When using docker_image, this is the path inside the container.
bin_path = "./compiler"
}
})
dependencies({
build = {
required = { "zoi:go", "native:make" },
optional = { "cargo:some-build-tool:additional build helper" }
},
runtime = {
required = { "native:openssl" }
}
})
Package Collection
A collection
is a meta-package that only installs other packages as dependencies.
-- collections/web-dev-essentials.pkg.lua
package({
name = "web-dev-essentials",
repo = "community",
type = "collection", -- Set the package type to 'collection'.
version = "1.0",
description = "A collection of essential tools for web development.",
tags = { "collection", "web", "devtools" },
maintainer = {
name = "Community",
email = "[email protected]"
}
})
-- The 'runtime' dependencies are the packages that will be installed.
dependencies({
runtime = {
required = {
"zoi:node",
"zoi:bun",
"native:git"
},
optional = {
"npm:pnpm",
"npm:serve",
"npm:typescript"
}
}
})
Service Package
A service
package is for applications that need to run in the background. Zoi can manage starting and stopping them.
-- services/my-database.pkg.lua
package({
name = "my-database",
repo = "community",
type = "service", -- Set the package type to 'service'.
version = "5.7",
description = "A lightweight database server.",
tags = { "service", "database" },
maintainer = {
name = "Your Name",
email = "[email protected]"
},
-- The 'service' block defines how to manage the service.
service = {
{
platforms = { "linux-amd64", "macos-amd64" },
start = { "my-database --config /etc/my-database.conf" },
stop = { "pkill my-database" }
}
}
})
install({
{
type = "binary",
url = "https://example.com/my-database-v" .. PKG.version .. "-" .. SYSTEM.OS .. "-" .. SYSTEM.ARCH,
platforms = { "linux-amd64", "macos-amd64" }
}
})
Library Package
A library
package installs shared/static libraries and header files. It can also generate a .pc
file for pkg-config
.
-- libs/my-library.pkg.lua
package({
name = "my-library",
repo = "community",
type = "library",
version = "1.2.0",
description = "A library for doing awesome things.",
tags = { "library", "c++" },
maintainer = {
name = "Your Name",
email = "[email protected]"
},
-- This block is used to generate the .pc file
pkg_config = {
description = "My Awesome Library",
libs = "-L/usr/local/lib -lmy-library",
cflags = "-I/usr/local/include/my-library"
}
})
install({
{
type = "com_binary",
url = "https://example.com/my-library/v" .. PKG.version .. "-" .. SYSTEM.OS .. "-" .. SYSTEM.ARCH .. ".tar.gz",
platforms = { "linux-amd64" }
}
})
Script Package
A script
package runs a series of inline shell commands instead of installing a binary. This is useful for complex setup actions.
-- my-setup-script.pkg.lua
package({
name = "my-setup-script",
repo = "community",
type = "script",
version = "1.0",
description = "A package that runs a series of setup commands.",
tags = { "script", "setup" },
maintainer = {
name = "Your Name",
email = "[email protected]"
},
-- The 'script' field contains the commands to run.
script = {
{
platforms = { "linux", "macos" },
install = {
"echo 'Creating configuration directory...'",
"mkdir -p ~/.config/my-app",
"echo 'hello: world' > ~/.config/my-app/config.yml"
},
uninstall = {
"echo 'Removing configuration...'",
"rm -rf ~/.config/my-app"
}
}
}
})
App Template Package
An app
package defines a template to scaffold applications via zoi create <source> <appName>
. It is not installable directly.
-- apps/rails-app.pkg.lua
package({
name = "rails-app",
repo = "community",
type = "app",
version = "7",
description = "Rails app template",
tags = { "app", "rails", "ruby" },
maintainer = {
name = "Your Name",
email = "[email protected]"
},
-- Platform-specific create command and optional follow-up commands
app = {
{
platforms = { "all" },
appCreate = "rails new ${appName}",
commands = {
"cd ${appName} && bundle install",
"cd ${appName} && git init"
}
}
}
})
dependencies({
runtime = {
required = { "zoi:@core/ruby", "zoi:@main/gems/rails" }
}
})
Extension Package
An extension
package modifies Zoi's configuration. It is managed with zoi extension add
and zoi extension remove
.
-- extensions/corp-repos.pkg.lua
package({
name = "corp-repos",
repo = "community",
type = "extension",
version = "1.0",
description = "Adds the official corporate package repositories for MyCorp.",
tags = { "extension", "config" },
maintainer = {
name = "MyCorp IT",
email = "[email protected]"
},
extension = {
type = "zoi",
changes = {
{ type = "repo-git", add = "https://git.mycorp.com/zoi-packages.git" },
{ type = "repo-add", add = "test" },
{ type = "registry-repo", add = "https://zoi-mirror.mycorp.com/Zoi-Pkgs.git" }
}
}
})
Last updated on